Ruby não tem um compilador para analisar as chamadas aos métodos.
Compiladores podem verificar por erros antes do código rodar, porém
essa proteção tem um custo alto, onde linguagens estáticas forçam o programador a escrever códigos repetitivos, como os os getters e setters do Java.
Vamos analizar um problema e refatorá-lo usando um pouco de metaprogramação.
Temos um banco de dados com objetos referentes a um Computador, como mouse, teclado e cpu. Um código legado busca informações sobre determinado Computador através de uma classe chamada BancoDeDados:
Argh..! Pra cada informação um método diferente. Muita repetição.
Vamos melhorar esse código.
Metaprogramação
Uma primeira idéia seria criar uma classe chamada Computador, que poderia receber os dados do banco e o id do computador procurado. Além disso poderia ser melhorada a questão dos métodos. Poderíamos ter métodos mais interessantes e expressivos, como mouse e cpu, retornando a informação.

É bem mais interessante trabalhar com a classe Computador. Porém..da-lhe repetição novamente. Pra criar informações de teclado seria um método praticamente copiado dos anteriores.
Dynamic Methods
Invocar um método significa enviar uma mensagem a um objeto. Isso pode ser feito da maneira tradicional, ou seja, “objeto ponto método”, ou através do método send.
O primeiro argumento do método send é o nome do método a ser invocado.
E por que você usaria essa notação ? Qual a vantagem em chamar um método através do send ?
Esse é um dos pontos mais interessantes da linguagem, pois com o método send os nomes dos métodos não são nada mais que argumentos. Strings!. Ou seja, você pode decidir a qualquer momento qual método vai chamar. Essa técnica é conhecida como Dynamic Dispatch.
Você pode ainda definir um método dinamicamente com o método define_method.
Refatorando
Ok. E onde usar isso tudo ?
Refatorando a classe Computador para invocar métodos através do método send conseguimos retirar muita duplicação:
Agora uma chamada ao método cpu delega para componente que utiliza o parametro string para invocar o método!
Muito melhor. Mas… ainda existe duplicação, cada componente tem um método de delegação, por que não utilizar o define_method visto anteriormente ?
Ha! Tomara que nesse momento você esteja lembrando de uma série de métodos encontrados em gems ou mesmo no Rails… ![]()
(Você ainda pode retirar essa última duplicação na definição dos componentes, pense um pouco)
Continua
Próximo post – method_missing()






Alan Rafael R. Batista
February 10, 2010
Ótimo post Anderson,
Achei que ficou falando exemplos com “missing_method” para comparar as duas abordagem.
No Core tem muitas situação de geração de métodos dinamicamente, porém por questões de performance (imagino) foram desenvolvidas em C, tais como “attr_accessor” do “Module”.
[]´s
anderson_leite
February 10, 2010
Oi Alan, obrigado pelos comentários. Method missing é o assunto do próximo post. Valeu!
Alan Rafael R. Batista
February 10, 2010
Ah… show de bola, vou ler o outro post então, rs.
[]´s
Alan Rafael R. Batista
February 10, 2010
Ah, acho também que se você tivesse colocado que ao invés de “uma chamada ao método cpu”, colocasse “enviar uma mensagem cpu…” ficaria mais claro, pq muitos programadores quando entram no mundo Ruby se esquecem de entender o “Ruby Way” e acabam não entendendo conceitos como esse demonstrou muito bem no seu Post.
Um link legal para uma introdução ao Ruby Way para programadores de outras linguagens é este http://onestepback.org/articles/10things/item8.html que se não me engano o Akita traduziu, só eu não estou encontrando.
[]´s
Jarbas
February 10, 2010
Cara, muito show seus últimos posts sobre metaprogramação e tomara que continue postando mais coisas sobre esses assuntos pouco abordados em nossa língua nativa.
Abraços
Guilherme Garnier
February 23, 2010
Acho que a melhor maneira de simplificar as 3 últimas linhas é:
[:mouse, :cpu, :teclado].each {|item|
define_component item
}
@maykoncapellari
May 16, 2010
Ótimo post já estou assinando o feed… sobre o artigo que o Alan Rafael R. Batista falou segue ai…
http://akitaonrails.com/files/10_coisas_que_todo_programador_Java_deve_saber.pdf
Abraços