Ruby inherited, come sapere quando viene create una sotto classe

Posted by Dibi Store Fri, 07 Mar 2008 16:20:00 GMT

A volte può essere utile conoscere quando viene creata una sotto classe di una particolare classe. Per questo può tornare utile il metodo di classe (scusate il gioco di parole) Class.inherited. Gli esempi seguenti sono auto esplicativi e non dovrebbero lasciare dubbi:


class Foo
  
  class << self  # => Uguale a def self.inherited...
    def inherited(sub_class)
      puts "Hai creato la sottoclasse #{sub_class}"
    end
  end

end

class Bar < Foo; end

Posted in  | Tags  | no comments | no trackbacks

Ruby define_method e module_eval: ancora sulla metaprogrammazione

Posted by Dibi Store Tue, 04 Mar 2008 10:28:00 GMT

Continuo la serie di articoli riguardo la metaprogrammazione in Ruby mostrando un paio di metodi molto utili. I metodi che seguono permettono di creare rispettivamente un metodo di istanza (ossia che disponibile successivamente aver istanziato la classe) e un metodo di classe (richimabile senza aver istanziato la classe). Questi metodi sono molto utilizzati ad esempio nel sorgente di rails e ci permettono di usare tutti quei metodi come validates_presence_of che ci vengono regalati in molte classi. Notate nel secondo esempio come usiamo in modo appropriato il codice class << self.

class Test; end
  
Test.module_eval do  
  define_method :talk do  
    puts "This is cool!"  
  end  
end  
  
Test.new.talk # => This is cool!


Test.module_eval do
  class << self
    define_method :talk_again do
      puts "This is more cool!"
    end
  end
end

Test.talk_again # => This is more cool!

Un applicazione reale? Immaginate di dover definire lo stesso metodo in dieci classi diverse contenute nell'array classi, potreste usare il codice seguente:

classi.each do |c|
  c.module_eval do
    define_method :validates... do |*args|
      ....
    end
  end
end

Notate che *args è un hash di argomenti che possono essere passati alla funzione, potete poi estrapolarli a vostro piacere. E' possibile anche dare un solo (o più) argomenti alla funzione con la seguente sintassi define_method :name do |arg1, arg2| ... end.

Risorse: documentazione modulo

Posted in  | Tags  | no comments | no trackbacks