ruby-on-rails ruby methods module nested

ruby on rails - ¿Cómo hacer que los métodos se agreguen a una clase al incluir módulos "anidados" para que sean métodos de instancia de esa clase cuando se usa la función ActiveSupport:: Concern?



ruby-on-rails methods (1)

Estoy usando Ruby 1.9.2 y la gema Ruby on Rails v3.2.2. Después de mi pregunta anterior sobre cómo "anidar" la inclusión de módulos cuando utilizo la función ActiveSupport :: Concern de Ruby on Rails , me gustaría saber dónde debo indicar los métodos agregados a una clase al incluir módulos "anidados" para poder hacer estos métodos de instancia de esa clase. Es decir, tengo lo siguiente:

class MyClass < ActiveRecord::Base include MyModuleA end module MyModuleA extend ActiveSupport::Concern included do include MyModuleB end end module MyModuleB extend ActiveSupport::Concern included do # def my_method # ... # end end # def my_method # ... # end end

¿ Debo indicar def my_method ... end en el "cuerpo" / "contexto" / "alcance" de MyModuleB o debería decir eso en el included do ... end ? ¿Cuál es la diferencia y lo que debería esperar de eso?


Los métodos en módulos que se mezclan en una clase se convierten en métodos de instancia en esa clase. Si bien ponerlos en el bloque included probablemente funcione, no hay necesidad de hacerlo. Esto, por extensión, funciona con módulos, ya que puede incluir el ModuleB en ModuleA y todos sus métodos de instancia se convierten en métodos de instancia en ModuleA , y una vez que se incluye ModuleA en la clase Foo , todos sus métodos de instancia (incluidos los mezclados desde B ) se convierten en instancia métodos en Foo.

Una mezcla "tradicional" se ve así:

module Mixin def self.included(klass) klass.send :extend, ClassMethods klass.some_class_method end module ClassMethods def some_class_method puts "I am a class method on #{self.inspect}" end end def some_instance_method puts "I am an instance method on #{self.inspect}" end end class Foo include Mixin end Foo.new.some_instance_method # Output: # I am a class method on Foo # I am an instance method on #<Foo:0x00000002b337e0>

ActiveSupport :: Concern solo se adelanta un poco al incluir automáticamente un módulo llamado ClassMethods y ejecutando el bloque included en el contexto de la clase incluida, por lo que el equivalente es:

module Mixin extend ActiveSupport::Concern included do some_class_method end module ClassMethods def some_class_method puts "I am a class method on #{self.inspect}" end end def some_instance_method puts "I am an instance method on #{self.inspect}" end end class Foo include Mixin end Foo.new.some_instance_method # Output: # I am a class method on Foo # I am an instance method on #<Foo:0x000000034d7cd8>