Quando temos um objeto em Ruby e mandamos uma mensagem a esse objeto, a primeira coisa que esse objeto faz é procurar um método com o mesmo nome da mensagem que foi enviada. Mas como assim?

Por exemplo, temos o seguinte código (veja os comentários):

class Cachorro
 
   # Aqui temos um método
   def latir
      puts "Au au"
   end
 
   def rosnar
      puts "grrrrrr"
   end
 
end
 
cao1 = Cachorro.new
 
# Aqui estamos enviando a mensagem latir ao objeto
# cao1
cao1.latir
 
cao1.rosnar

Saída:

Au au
grrrrrr

Repare que temos a classe “Cachorro“. Nessa classe temos dois métodos: latir e rosnar. Terminada a classe, vem o script. No script criamos um novo objeto cachorro com o nome de “cao1“. Quando declaramos cao1.latir ou cao1.rosnar, estamos mandando uma mensagem ao objeto.

Quando mandamos essa mensagem, o objeto cao1 procura pelo primeiro método que ele encontrar com o mesmo nome da mensagem. O nome da mensagem é “latir” e “rosnar” no nosso caso.

Muito bem, agora o que aconteceria se chamássemos um método que não exista nesse objeto? Ou melhor, se mandássemos uma mensagem que não exista a esse objeto?

Veja o exemplo e a saída:

class Cachorro
 
   def latir
      puts "Au au"
   end
 
   def rosnar
      puts "grrrrrr"
   end
 
end
 
cao1 = Cachorro.new
 
cao1.latir
cao1.rosnar
 
# Método não existente
cao1.voar

Saída

Au au
grrrrrr
C:/desenvolvimento/ML/Estudo/lib/main.rb:23: undefined method `voar’ for #<Cachorro:0x2909af0> (NoMethodError)

Resumindo, o Ruby quando não encontra o método, levanta a exceção “NoMethodError“. Agora vem a parte mais legal. Nós podemos tratar esse erro capturando a exceção ou, utilizando o method_missing. Mas o que é o method_missing?

Após a verificação de que não existe aquele método chamado pelo objeto, o Ruby antes de levantar a exceção, procura pelo method_missing, se existir, a exceção não é levantada e esse método é chamado. Vamos ao código!

class Cachorro
 
   def latir
      puts "Au au"
   end
 
   def rosnar
      puts "grrrrrr"
   end
 
   def method_missing(m, *args)
      puts "Putz! Chamei o metodo errado"
   end
 
end
 
cao1 = Cachorro.new
 
cao1.latir
cao1.rosnar
 
# Método não existente
cao1.voar

Saída:

Au au
grrrrrr
Putz! Chamei o metodo errado

Muito legal!

O method_missing é uma maneira elegante e muito “rubística” de tratar chamadas de métodos inexistentes. Mais do tratar esse tipo de erro, você pode usar para criar novas funcionalidades em seu sistema. O Rails usa e abusa do method_missing.