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>