Programação automática: escreve código que escreve código [fechado]

104

Depois de ler o livro The Pragmatic Programmer , um dos argumentos que achei mais interessante foi "escrever código que escreve código ".

Eu tentei pesquisar na net para mais explicações ou artigos sobre isso, e embora eu tenha encontrado alguns bons artigos sobre o assunto, ainda não encontrei nenhuma implementação de código específico ou bons exemplos.

Eu sinto que ainda não é um argumento tão comum, algo que carece de documentação ou não é aceito por tantas pessoas, e eu gostaria de saber mais sobre isso.

O que você acha sobre o assunto? É algo que realmente aumentará sua produtividade? Quais são alguns bons recursos sobre o assunto, entre livros, blogs, slideshows, etc?

Alguns exemplos de código seriam muito apreciados para permitir que eu compreendesse melhor sua implementação.

Aqui está a página wiki sobre o assunto, com várias técnicas de programação relevantes, como Meta Programming, Generative Programming e Code Generation.

    
por Jose Faeti 13.01.2012 / 03:42
fonte

22 respostas

47

No mundo Lisp, é bastante comum ver o código que escreve código que escreve código (e assim por diante). Portanto, qualquer projeto Lisp ou Scheme de tamanho decente servirá como um bom exemplo de código. Eu recomendo olhar para o compilador Racket e fontes de tempo de execução, bem como Bigloo , suas bibliotecas são simplesmente brilhantes.

Quanto à produtividade: estou usando a metaprogramação como uma técnica dominante em quase todo o meu trabalho de desenvolvimento, e isso claramente ajuda muito, reduzindo o tamanho do código e aumentando a legibilidade. A chave está no uso de Idiomas específicos do domínio , e a metaprogramação é uma das maneiras mais eficientes de implementá-las.

    
por 26.08.2011 / 11:39
fonte
67

Eu prefiro ir um pouco mais longe e, em vez de escrever código que escreve código, escrever código que gera objetos, métodos, funções. Isso pode ser obtido com macros Lisp ou recursos de modificação dinâmica de programas Ruby, por exemplo.

A pequena diferença é que você não termina com arquivos de origem que foram gerados automaticamente. Normalmente, esses arquivos não são legíveis para humanos e não podem ser modificados, então por que se preocupar com eles? Eu não gosto da ideia de aumentar minha base de código com algo que não posso controlar.

Um livro que eu gostei de ler sobre o assunto foi Metaprogramming Ruby (se você conhece a linguagem Ruby)

Edite após a seguinte pergunta no comentário:

Why should it be useful it I still have to code the generating code? Should I write a code able to generate different things depending on user input, so that I can reuse it over and over?

Primeiro, a metaprogramação não é uma meta, mas uma ferramenta. Não use metaprogramação porque "é legal" ou "X disse que todo desenvolvedor deve usá-lo".

Acho que uma boa razão para usar a metaprogramação é generalizar algum padrão comum (padrão como algo que se repete) que você encontrou em seu código e que nenhuma outra técnica de programação usual (herança, padrões de design, etc.) pode alcançar.

Como dito pela Jordânia , Um caso de uso típico é o manuseio de banco de dados e o ORM (Mapeamento de Relação de Objeto). Mais uma vez, em Ruby, você deve olhar para ActiveRecord que é um ótimo exemplo de metaprogramação aplicada ao ORM.

Como nota final:

Não pense "Eu quero aplicar metaprogramação, onde eu poderia aplicá-lo no meu código?".

Pense "Eu vejo esse padrão que está se repetindo em todo o meu código, não consigo encontrar uma maneira de refatorar o código em algo menor e mais reutilizável. Talvez metaprogramação pode me ajudar? "

    
por 12.04.2017 / 09:31
fonte
19

Melhor ainda, use o código que alguém escreveu e que escreve seu código para você.

A automação de código geralmente é boa para ORMs e outros códigos de interação de banco de dados e, é claro, para construção de código repetitiva, mas semelhante.

É claro que, se você está criando muitas classes parecidas, talvez você tenha conseguido a mesma coisa em uma linguagem dinâmica muito mais cedo, mas eu discordo.

Isso é adotado por muitas pessoas, embora você frequentemente encontre o software rotulado como geradores de código.

Veja empresas e produtos como CodeSmith e MyGeneration ou navegue neste artigo da Wikipédia: link

    
por 26.08.2011 / 09:52
fonte
16

Um dos exemplos clássicos é lex e yacc. Seu objetivo principal é evitar o trabalho penoso de escrever qualquer tipo de analisador. Ao longo do caminho, eles tornam muito mais rápido a construção de analisadores complexos com muitas regras e estados, e também evitam todos os erros de surpresa cometidos por pessoas que rendem seus próprios erros.

Esta é também a ideia por trás do c, que é uma ferramenta para escrever o assembler. O mesmo vale para qualquer linguagem de alto nível que você queira nomear. Para ferramentas que escrevem código para você, existem alguns paradigmas simples.

Um IDE adequado ajuda fornecendo documentação na ponta dos dedos, preenchimento automático inteligente e snippets de código. O IDE também inclui vários modelos, para que você não precise iniciar um programa do zero. Existem programas para obter um diagrama de uml e classes aproximadas em uma linguagem de alto nível.

Finalmente, você pode escrever suas próprias ferramentas para geração de código dentro do seu conjunto de problemas. É assim que o lex e o yacc começaram. Qualquer tipo de linguagem específica de domínio existe exatamente por esse motivo. Você cria alguns blocos de construção que descrevem sua solução em código mais fácil de entender, encerrando atividades comuns ou seções complicadas com comandos simples. Você não está procurando uma solução para o problema todos , apenas uma definição mais fácil do problema específico com o qual você está lidando.

De certa forma, tudo o que você faz acima da camada binária é a automação de código.

    
por 26.08.2011 / 14:50
fonte
13

Metaprogramação

A metaprogramação é uma técnica controversa em muitas lojas. A razão é que, como qualquer ferramenta poderosa, a magnitude da ajuda ou da mágoa é grande.

Prós

  • Mais expressivo, menos código para escrever e manter (geralmente em uma ordem de magnitude ou mais)
  • Consistência, comportamento mais consistente sobre a classe de problemas que você resolve com o código
  • Produtividade, menos código para uma solução para um espaço maior do problema

Contras

  • Complexidade, pode ser muito complicado mesmo que haja menos código
  • Segurança, por vezes, segurança de tipo e análise estática em geral serão sacrificadas
  • Erros afetam mais, pequenos erros terão um impacto maior

Sou um grande fã de metaprogramação, mas faço isso há muito tempo. Para mim, a desvantagem do tamanho reduzido do código e do comportamento consistente é mais do que compensar os riscos. Menos código significa menos bugs, menos código para manter, e eu geralmente posso adicionar grandes partes da funcionalidade muito rapidamente.

No entanto, isso não significa que todos os programadores devam se envolver com isso. Eu vi e tive que consertar grandes problemas criados pela metaprogramação. Normalmente, quando as pessoas não entendem o conceito e tentam estender a funcionalidade, ou apenas consertam um bug. É preciso uma mentalidade particular que seja, no mínimo, orientada para detalhes. A questão de usar técnicas de metaprogramação deve ser uma decisão da equipe . Se você tem membros da equipe que não entendem, não têm o temperamento para isso, ou são apenas contra ele, nenhum dos membros da equipe deve usar a metaprogramação.

    
por 06.09.2011 / 07:04
fonte
9

A maioria dos códigos de código escreve. Por exemplo, o código PHP ajuda a escrever html. A biblioteca php pdo ajuda a escrever chamadas SQL. As funções de E / S do arquivo gravam código para se comunicar com o sistema operacional. Até mesmo uma chamada de função regular é uma referência a outro bloco de código que é executado. Então, as chamadas das suas funções estão escrevendo código.

Em termos gerais, podemos pensar em computação como códigos de escrita que escrevem códigos de forma recursiva, formando uma pilha que termina quando se depara com a realidade física dos códigos ligados ao hardware.

    
por 26.08.2011 / 19:26
fonte
5

Como você faz isso varia dependendo de seus requisitos. Supondo que você esteja usando a geração de código estático, você mesmo poderia escrever toda a infraestrutura ou usar um gerador existente, como o CodeSmith ou o MyGeneration. Usando estes você só precisa escrever os modelos necessários.

Meu último projeto envolveu algumas telas básicas do ASP.NET CRUD (a geração de código é boa para isso). O processo foi definir entidades como metadados em arquivos xml. Escrever modelos para cobrir os vários artefatos necessários (classes de entidade, repositórios, classes de serviço, controles asp.net, páginas asp.net etc.). Execute o processo de geração e estilize a saída.

Existe alguma sobrecarga na escrita dos modelos, mas eles podem ser reutilizados para projetos semelhantes subsequentes. Da mesma forma, as alterações nos dados subjacentes são tratadas pela alteração dos metadados e pela nova execução, tornando as alterações mais simples e rápidas de implementar.

Quanto ao teste. Como esse é um sistema com modelo, você precisará passar algum tempo validando inicialmente a saída do processo. Se o modelo estiver errado, todas as saídas desse modelo estarão igualmente erradas. Uma vez que você está feliz com isso, você também pode usar os geradores de código para criar testes básicos a partir dos metadados xml que você pode estender para cobrir casos especiais. No entanto, lembre-se de que você ainda pode precisar entregar testes de código para atender a itens específicos, a geração de código reduz o seu trabalho, não o elimina totalmente.

    
por 26.08.2011 / 11:36
fonte
5

Na nossa empresa, usamos algumas ferramentas que realmente geram classes C ++ ou C # com dados baixados da Internet. Essas classes são contêineres de dados e contêm um grande número de objetos nas listas.

    
por 26.08.2011 / 16:48
fonte
5

A metaprogramação faz parte da programação há muito tempo. Considere não apenas ferramentas como SWIG, ou designers WYSIWYG, que criam código, mas também ferramentas em linguagem como o pré-processador de C, ou mesmo modelos de C ++ e genéricos de C # / Java - para não mencionar o Reflection.

Na verdade, você poderia argumentar que todo compilador é apenas outro metaprograma - eles pegam texto de programa e máquina de saída ou código de VM. E a vida sem compiladores? Owch.

    
por 28.08.2011 / 12:10
fonte
5

Aqui está um exemplo concreto do meu passado.

Eu estava trabalhando em um site que tinha cerca de 50 MB de código-fonte do Delphi usando o BDE para acesso a dados. Eles queriam usar o Direct Oracle Access para permitir uma atualização do Oracle após a versão mais alta suportada pelo BDE (8i se bem me lembro).

Portanto, em vez de fazer com que uma equipe de programadores trabalhasse com todos os módulos de formulários e dados, alterando cada componente manualmente, escrevi um script PERL que: -

  1. Analisou o DFM (arquivo de formulário) e identificou todos os TQuery, TTable, TStoredProcedure & Objetos TDatabase - armazenando os itens em uma lista.

  2. Analisou o PAS (código) e identificou o uso dos objetos - as TQueries estavam fazendo atualizações ou seleções? Além disso, identificou quaisquer objetos criados no código em vez de serem descartados em um formulário no IDE.

  3. Reescreveu o DFM & PAS alterando os tipos de objetos adequadamente (por exemplo, TTable - > TOracleDataSet com a propriedade SQL definida como "selecionar * de" etc.) e as chamadas de método. Além disso, foram adicionadas chamadas de método adicionais, se apropriado, para fechar, abrir & definir parâmetros.

Em suma, 3 semanas trabalham com o script para trabalhar em diferentes aplicativos escritos por equipes diferentes com diferentes estilos de codificação, em vez da estimativa original de 5 ou mais desenvolvedores trabalhando por 6 meses.

E a razão pela qual eu até pensei em usar essa abordagem foi através da leitura do The Pragmatic Programmer

    
por 06.09.2011 / 07:33
fonte
4

Você pede exemplos ...

Ao trabalhar com SQL, você não deve estar alterando o banco de dados diretamente, mas sim executando scripts que fazem as alterações desejadas, incluindo mudanças estruturais no banco de dados (adicionando tabelas, colunas, chaves primárias, restrições e assim por diante). Com muita frequência, você precisará executar a mesma ação contra muitas tabelas ou colunas ao mesmo tempo, e executá-las uma por uma seria tedioso, um script curto que gera um script maior que faz o que você quer pode ser um verdadeiro economizador de tempo.

Por exemplo, antes de o tipo de dado DATE ser introduzido no MS SQl Server, a única escolha para uma coluna de data era DATETIME, que tem uma parte de tempo - uma parte de tempo que dificulta lidar com os dados. Ao atualizar para uma versão com o tipo de dados Data, você pode querer atualizar as colunas onde a hora é sempre 00:00. Em um banco de dados com dezenas ou até centenas de colunas DateTime, isso consumiria bastante tempo. Mas é fácil escrever um script que consulta todas as tabelas, verificando cada coluna com um tipo de dados de DATETIME para ver se a hora é qualquer coisa, exceto 00:00 e, se não, criar uma instrução ALTER para a tabela / coluna para alterar o tipo de dados para DATE. Presto, código que escreve código.

    
por 10.08.2012 / 20:32
fonte
3

Dê uma olhada nas macros CL (Lips comuns). Na minha opinião, isso é exatamente o que você quer. Lábios é perfeito em metaprogramação.

Também sugiro Nemerle se você quiser ter poderes .NET com suporte perfeito à metaprogramação (incluindo macros)

Mas se você quiser um verdadeiro mecanismo de geração de código, dê uma olhada na Parcela de pagamento do Apache

    
por 29.08.2011 / 10:27
fonte
3

Estou apenas trabalhando em tal ferramenta. Em nosso caso particular, geramos o código VB.NET baseado na camada de dados nas assinaturas das funções no banco de dados.

Começar a trabalhar em e com a geração de código é difícil no início, já que você não tem ideia de como o código deve ser gerado, mas depois de ter um conjunto estabelecido de regras e o código necessário ser gerado sempre pode ser gerado com base nessas regras, trabalhando com esse código não é tão difícil. É claro que, dependendo da complexidade da geração de código e do número de regras, a tarefa pode se tornar mais difícil. Mas, em essência, a geração de código automático é usada para tarefas repetitivas de codificação e não para código avançado que varia muito.

Teste a saída é dupla. Primeiro você tem que se certificar de que o código compila, e isso é fácil. Então você tem que ter certeza de que a saída faz o que você queria fazer com base nos parâmetros em que ela foi gerada ... e a dificuldade disso varia na complexidade do código que você gera.

Minha sincera recomendação é que se você sentir que escreve o código de uma maneira repetitiva , e você pode arcar com o tempo. Tente pensar se o que você está fazendo não pode ser gerado código. E se assim for (se é um código repetitivo do que quase sempre é o caso) pense quantas vezes você terá que estender, modificar ligeiramente esse código e também quantas vezes você tem que escrever esse tipo exato de código. Se a resposta a qualquer um destes é "muitos", então você deve considerar seriamente criar um gerador para esse código .

Espero que ajude,
IPP

    
por 29.08.2011 / 12:27
fonte
3

Eu tenho um módulo PHP que gera uma página web contendo código JavaScript que gera HTML. São três camadas bem ali. Rapaz era tão difícil de ler!

Em uma classe de programação, tínhamos que escrever um programa que pegasse uma string de fórmula do usuário e a analisasse e exibisse o valor. O solucionador mais impressionante simplesmente pegou a entrada do usuário, empacotou em main () {printf ("% d", ...);} e executou um script para compilar, vincular e executá-lo. Ele não escreveu um analisador! Hoje você poderia fazer isso em uma instrução SQL SELECT.

É uma ferramenta que você deve usar para armazená-la em algum dia no futuro, quando for útil.

    
por 06.09.2011 / 11:07
fonte
3

Desenvolvi soluções de meta-programação meticulosas com Prolog . Onde o aplicativo principal (em linguagem C ++) traduz uma definição abstrata de um problema em um aplicativo Prolog em tempo de execução, que é então delegado para. Muitas vezes, escrever uma funcionalidade equivalente em C ++ levaria uma eternidade.

Acho que esse cenário é um excelente caso em favor do argumento code-writing-code .

    
por 06.09.2011 / 14:35
fonte
3

O que você acha sobre o assunto?

A metaprogramação é mais comumente associada a linguagens não-dinâmicas, uma vez que é mais difícil atingir certos comportamentos (como implementar um ORM) sem muitas linhas de código não produtivas e não-inteligentes.

Mas, mesmo em linguagens mais dinâmicas, como o PHP, a geração de código pode realmente salvar vidas e aumentar a produtividade em grande quantidade. Em estruturas modernas, é muito comum ter um scaffold que gere a maior parte do modelo, forma, teste e ações comuns para um determinado objeto de negócio que você declara. É uma das razões pelas quais frameworks como o symfony ou o RoR têm tanto sucesso, essas ferramentas de geração de código fazem código consistente muito rapidamente e aumentam a produtividade dos programadores.

Nos sites, a maior parte da interação gira em torno de quatro ações principais:

  • Crie um elemento
  • Recuperar um conjunto de elementos (com possível filtragem)
  • Atualize um elemento com novos atributos
  • Excluir um conjunto de elementos

Pelo menos tudo o que gira em torno dessas 4 ações principais poderia e IMHO DEVE ser alcançado usando ferramentas de geração de código para alcançar a máxima produtividade.

Na minha empresa, usamos o symfony, e seu admin-generator é uma ferramenta excepcional, que gera código em tempo de execução (e armazena em cache), o que significa que nem precisamos usar qualquer tipo de tarefa ou ferramenta externa para gerar novo código, só precisamos limpar nosso cache. Eu recomendo vivamente a utilização deste tipo de ferramenta para operações CRUD.

Mas, fazer o que os contribuidores incríveis do symfony fizeram, não é uma tarefa fácil. Já implementei algumas tarefas de geração de código e fazer algo que seja realmente consistente e com uma implementação ampla para cobrir a maioria dos casos-chave não é fácil.

É algo que realmente aumentará sua produtividade?

Eu acredito que a metaprogramação é muito importante em níveis mais baixos de trabalho (frameworks, caching, compiladores, etc.), mas algo que devemos abordar com extrema cautela se estamos fazendo coisas na camada de negócios.

Usar a geração de código é, sem dúvida, um grande impulsionador da produtividade. Implementando suas próprias ferramentas de geração de código, não muito, a menos que você esteja construindo uma estrutura por conta própria.

Quais são alguns bons recursos sobre o assunto, entre livros, blogs, apresentações de slides, etc.

O melhor recurso para entender a programação é sempre um código-fonte bom e bem comentado. Eu diria que olhando para RubyOnRails e Geradores de administração do symfony é uma boa idéia.

    
por 12.05.2012 / 13:13
fonte
3

Embora muitas respostas aqui se refiram ao que é comumente conhecido como metaprogramação, havia de fato um campo associado à IA conhecido como programação automática que era sobre programas entendimento ou sintetizando programas [1].

Qualquer compilador (ou metaprograma, gerador de código, tradutor, sistema de macro, ...) trabalha com transformações, gerando uma saída a partir de uma entrada executando seu algoritmo fixo de transformação. Mas um compilador ou metaprograma tradicional não, dada uma definição, descrição ou exemplo de como classificar uma lista é (por exemplo, [5, 3, 9] = > [3,5,9]), cria um algoritmo de classificação . Tais problemas são de interesse do campo "programação automática".

[1] - Relatório de progresso sobre sistemas de compreensão de programas ftp://db.stanford.edu/pub/ cstr / reports / cs /.../ CS-TR-74-444.pdfPartilhar

    
por 18.02.2013 / 04:35
fonte
2

Meta programação pode ser muito difícil de manter. No começo parece elegante, mas quando você começa a correr em casos de canto, os erros são capturados tarde (no código que foi gerado), e a coisa toda se torna um pesadelo para usar / depurar.

Eu escrevi principalmente código python e, na minha experiência, a meta-programação é sempre uma má escolha com essa linguagem. Você sempre pode refatorar as coisas para fazê-lo com os recursos normais da linguagem. O resultado é menos divertido, mas mais fácil de viver.

    
por 28.08.2011 / 12:50
fonte
2

OP pede recursos.

Você pode encontrar o nosso DMS Software Reengineering Toolkit interessante. Trata-se de uma ferramenta de metaprogramação pura, destinada a permitir a criação de ferramentas personalizadas de análise e transformação de programas.

[Para seguir um comentário à pergunta do OP, quando usado para construir uma ferramenta de transformação específica, o DMS é uma linha de produto que escreve código, que escreve código:]

O DMS consegue isso agnóstico (mas não independente) de lanuages de programação de destino. O DMS fornece os serviços padrão necessários para uma ampla variedade de tarefas de metaprogramação, assim como um sistema operacional fornece uma ampla variedade de serviços para tarefas de programação padrão. Esses serviços incluem strong análise, construção automática de árvores de sintaxe abstact, correspondência de padrões e reescrita em árvores, bibliotecas de tabelas de símbolos que gerenciam facilmente linguagens com regras desagradáveis de escopo, como herança múltipla, fluxo de controle, fluxo de dados, pontos e chamadas análise gráfica. Nada disso é significativo na ausência de linguagens específicas a serem processadas, portanto, o DMS aceita definições de linguagem vinculadas a essas peças gerais de máquinas, produzindo análise específica de linguagem, construção de AST, correspondência / reconfiguração de padrões específicos de idioma de destino usando o destino sintaxe da linguagem, analisadores específicos da meta-langauge, etc.

E como um sistema operacional, o DMS é projetado para ter pouquíssimas opiniões ou restrições sobre quais (meta) programas você deseja escrever, o que significa que ele pode ser usado para várias finalidades: extração de métricas, localização de código morto e implementação tecelões, traduzindo idiomas, gerando códigos a partir de DSLs, reestruturando grandes aplicações. (O DMS já foi usado para todas essas tarefas).

É necessário ter definições de linguagem robustas se você não quiser gastar seu tempo codificando tudo no manual de referência da linguagem (pense no que isso significa para Java e C ++). O DMS resolve esse problema com uma biblioteca de definições completas de langauge disponíveis. O analógico aqui é como ter um banco de dados avaialbe para o seu sistema operacional; você não precisa implementar um deles para escrever seu aplicativo centrado no banco de dados.

    
por 05.12.2011 / 03:13
fonte
2

Veja o conjunto de problemas 4 de Philip Greenspun no curso 6.916 do MIT: Engenharia de Software de Serviços da Web Inovadores ( link ).

Seu objetivo diz: "Ensine aos alunos as virtudes dos metadados. Mais especificamente, eles aprendem a representar formalmente os requisitos de um serviço da Web e, em seguida, criam um programa de computador para gerar os programas de computador que implementam esse serviço".

Este é um dos conjuntos de problemas que os recrutas de ArsDigita ( link ) precisavam resolver durante a primeira bolha.

O livro "SQL for Web Nerds" que Philip mencionou no pset foi movido para ( link ).

    
por 12.05.2012 / 11:44
fonte
2

Por volta de 2001, comecei a trabalhar em um projeto que fazia uso extensivo de objetos de negócios e objetos de dados. Eu deveria estar construindo o site de front-end, mas estava pendurado em meus dedos porque a camada de negócios e a camada de acesso a dados não estavam totalmente desenvolvidas. Depois de algumas semanas disso, comecei a dar uma olhada no que essas camadas estavam fazendo. Basicamente, eles estavam expondo dados retornados de procedimentos armazenados como coleções de objetos com propriedades correspondentes aos campos nos dados, ou estavam recebendo parâmetros de entrada e enviando-os para procedimentos armazenados para serem salvos em tabelas de banco de dados. Houve muita serialização / desserialização ocorrendo entre as duas camadas, havia o Microsoft Transaction Server envolvido, uma biblioteca de tipos IDL / ODL ... mas tudo se encaixava em um padrão.

Duas semanas depois, eu tinha um gerador de código funcionando, que despejava IDL / ODL, e também despejava os objetos de negócios e dados. Levou o cara construindo os objetos business e layer de dados 2 anos para chegar ao ponto de depurar e testar esses objetos. Em 2 semanas, com a geração de código, tivemos a mesma saída, mas como tudo foi gerado, ficou muito bem sem erros.

Esse gerador de código (ferramenta CASE de nível mais baixo) me acompanhou por muitas iterações diferentes, por cerca de 8 a 10 anos, porque o princípio era simples: você está fazendo algo que precisa ser feito ao conversar com bancos de dados é uma codificação praticamente repetitiva e, depois de acertar, você não precisa mais se preocupar com isso.

Então, sim: use um gerador de código, particularmente quando a codificação é repetitiva e se encaixa em um padrão bem definido.

Eu sei que as pessoas usam macros RegX para fazer coisas semelhantes ou usar fórmulas do Excel para fazer coisas semelhantes (eu também faço isso).

    
por 12.05.2012 / 21:58
fonte
2

Um exemplo de metaprogramação

Eu tenho uma biblioteca de autorização em Ruby chamada Authority . Ele permite que os desenvolvedores façam perguntas em seus aplicativos com métodos como current_user.can_read?(@post) e @post.readable_by?(current_user) . Essas perguntas são respondidas por classes de autorizador centralizadas.

Esta é a parte crucial: A autoridade não sabe quais métodos definir até ver a configuração do usuário . A configuração do usuário pode conter:

config.abilities =  {
  ...
  :read      => 'readable',
  :microwave => 'microwavable',  # user-defined
  ...
}

Nesse caso, é preciso haver um método como current_user.can_microwave?(@post) .

A metaprogramação torna isso possível: depois de ler a configuração, eu sei quais métodos definir :

Authority.verbs.each do |verb|
  class_eval <<-RUBY, __FILE__, __LINE__ + 1 # allows for a nice bracktrace
    def can_#{verb}?(resource)
      resource.#{Authority.abilities[verb]}_by?(self)
    end
  RUBY
end
    
por 12.05.2012 / 22:02
fonte