Devido a natureza dinâmica do Ruby, o método respond_to? é crucial. Quantas vezes não precisamos checar se um método existe no objeto que estamos manipulando, ou mesmo verificar se o objeto é mesmo aquele que estamos esperando (is_a?)?
Porém tem algo muito importante que muita gente se esquece. Veja por exemplo esta minha classe que faz uso do método method_missing:
if method.to_s =~ /^latir/
puts "auau!"
else
super
end
end
end
rex = Cachorro.new
rex.latir #=> auau!
rex.latir! #=> auau!
rex.latir_e_correr #=> auau!
Acho que você já deve conhecer o method_missing, não? Veja que no exemplo acima eu estou criando uma instância da classe Cachorro e chamando os métodos latir, latir! e latir_e_correr que não existem. Por isto o método method_missing é disparado, onde eu uso uma expressão regular simples para retornar “auau!” caso o nome do método comece com a expressão latir.
Mas veja o que acontece quando tento usar o método respond_to?:
rex.respond_to? :latir #=> false
rex.latir #=> auau!
Ele retorna false, e isto faz todo o sentido já que o método realmente não existe. Então fica na minha responsabilidade alterar o método respond_to? para que ele funcione direito usando esta minha regra especial. Vou alterar minha classe para isto:
METODO_LATIR = /^latir/
return true if method.to_s =~ METODO_LATIR
super
end
if method.to_s =~ METODO_LATIR
puts "auau!"
else
super
end
end
end
rex = Cachorro.new
rex.respond_to?(:latir) #=> true
rex.latir #=> auau!
Agora sim! Este é um erro comum que tenho visto em alguns códigos, inclusive no próprio Rails, tente executar um respond_to? para verificar a existência de métodos como find_by_name, por exemplo.
Ruby é uma linguagem impressionante e flexível ao máximo, mas se não tomarmos cuidado podemos deixar pontas soltas como esta.
[Atualização]
Acabei de ver que no Rails 2.1 corrigiram este problema, poderemos usar o respond_to? para verificar a existência de métodos como o find_by_alguma_coisa.


Carlos, essa coisa de ser assim no rails, realmente eu jah apanhei sobre isso.
A algum tempo eu venho desenvolvendo uma forma de mover meus testes para dentro da lib e deixa-los mais genericos, mas infelizmente isso ainda tah bem sujo, pois NAO eh tao simples quanto parece modularizar os testes.
De qqr forma, eu criei alguns methodos que servem pra tu testar reacionamentos, e logo apanhei para isso que tu citou… para os testes ficarem genericos, uma coisa principal a ser testada eram os respond_to? dos methodos como <<, build, count, other_ids, etc, pra ver se os helpers daquele relacionamento estam lah! Pra minha surpresa, varios helpers NAO estavam lah segundo o respond_to?. Alguns que lembro agora que nao estao lah eh o count, o destroy_all e o other_ids.
Como na minha equipe eu prego muito a questao de “modularizar” coisas, separando-as em plugins, engines ou simplesmente em libs proprias com eh o caso dos testes, eu vejo muito este tipo de problema que tu citou, e tenho pensado em qqr hr parar para projetar uma DSL justamente para este tipo de coisa, de forma que jah consigas por exemplo suprir um methodo para uma regexp do method missing e ele sobrescreva tbm o respond_to? e tbm para coisas como gerar proxies entre methodos de classes, algo como um alias, mas entre classes diferentes (que jah usei pra N propositos, iunclusive para um plugin que tenho aqui, que “adiciona dinamicamente” campos para um modelo qqr - na verdade ele apenas gera um vinbculo atraves de proxy com um modelo com “campos customizados”).
[...] Usou o method_missing, então não deixe pontas soltas [...]