【问题标题】:How to make methods added to a class by including "nested" modules to be instance methods of that class when using the ActiveSupport::Concern feature?使用 ActiveSupport::Concern 功能时,如何通过将“嵌套”模块包含为该类的实例方法来将方法添加到类中?
【发布时间】:2023-03-29 06:37:01
【问题描述】:
我正在使用 Ruby 1.9.2 和 Ruby on Rails v3.2.2 gem。在我上一个关于how to “nest” the inclusion of modules when using the Ruby on Rails ActiveSupport::Concern feature 的问题之后,我想通过包含“嵌套”模块来了解我应该在哪里声明添加到类的方法,以便使这些类的这些实例方法。也就是说,我有以下内容:
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
应该我应该在MyModuleB 的“正文”/“上下文”/“范围”中声明def my_method ... end,还是应该在included do ... end 块中声明? 有什么区别以及我应该从中得到什么?
【问题讨论】:
标签:
ruby-on-rails
ruby
methods
module
nested
【解决方案1】:
混合到一个类中的模块中的方法成为该类的实例方法。虽然将它们放在included 块中可能会起作用,但没有必要这样做。通过扩展,这适用于模块,因为您可以在ModuleA 中包含ModuleB,并且它的所有实例方法都成为ModuleA 上的实例方法,并且一旦ModuleA 包含在类Foo 中,它的所有实例方法(包括那些从 B 混入的)成为 Foo 上的实例方法。
“传统”混音如下所示:
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 只是通过自动包含一个名为 ClassMethods 的模块并在包含类的上下文中运行 included 块来美化这一点,因此等效的是:
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>