O mistério do define_method

class Here

    def initialize
        defineMe("RJ")
        defineMe("SP")
    end
       

    def defineMe(dest)
      define_method(dest) do
         puts "Going here #{dest}"
      end
   end
end

h = Here.new

Só que não funciona:

C:\>ruby here.rb
here.rb:10:in `defineMe': undefined method `define_method' for #<Here:0x2838220>
 (NoMethodError)
        from here.rb:4:in `initialize'
        from here.rb:16:in `new'
        from here.rb:16

Ouvi falar que tem que definir como self.defineMe, mas não consegui fazer funcionar de jeito nenhum.

Alguma mente caridosa poderia me explicar o que é “def self.defineMe” e como fazer isso funcionar?

[code=Ruby]
class Simple

def initialize

Simple.send( :define_method, 'my_method' ) do
  p "esse é o my method"
end

Simple.send( :define_method, 'my_other_method' ) do |first_param, second_param|
  p "esse é o outro metodo, parametros -> #{first_param} - #{second_param}"
end

end

end

novo = Simple.new
novo.my_method
novo.my_other_method( 1, 2 )[/code]

Eu entendi que o método define_method é um método estático (da classe).

Eu tentei fazer o método estático com self.defineMe e chamei Here.defineMe no initialize, mas não funcionou.

Por que o meu código não funciona?

Teria como modificá-lo para fazer ele funcionar?

Valeu mesmo Maurício !!! Você é o cara!

Estranho, isso aqui funcionou para mim:

[code] class Here

   def initialize  
       Here.defineMe("RJ")  
       self.class.defineMe("SP")  
   end  
        
 
   def self.defineMe(dest)  
      define_method(dest) do  
        puts "Going here #{dest}"  
    end  
 end  

end

h = Here.new
h.RJ
h.SP[/code]

Aqui tb funcionou… Acho que fiz caca aqui então…

Mas me diz uma coisa self. antes do método transforma aquele método em estático, é isso?

Agora o interessante é que num método de instancia:

self.class.define_method não funciona.

Parece que ele é um método static protected, é isso?

Seu primeiro exemplo não funconou porque não existe o método define_method na instância, só existe na classe. O exemplo do Linhares funciona porque ele manda uma mensagem para a classe e não para o objeto, e com send() você pode acessar métodos privados. o exemplo do rubinelli funciona porque ele define um método público na classe que acessa o método privado para voc6e.

Ele é um método das classes e privado.

Ser métodos das classes significa que ele está definido na classe Class:

class Class
  private
  def define_method(...) ... end
end

Não é como o ‘static’ do Java, mas você pode começar olhando assim.

Para explicar melhor, acontece o seguinte: Here é uma constante que aponta para um objeto da classe Class. Quando você faz “def Here.defineMe”, o runtime Ruby cria uma metaclasse para esse objeto, e insere o método que você especificou. A partir daí, quando você chama um método nesse objeto (que por acaso é do tipo Class), a metaclasse é a primeira a ser checada na árvore de herança para ver se existe esse método.