2

我正在使用 Ruby 1.9.2 和 Ruby on Rails v3.2.2 gem。在我之前关于在使用 Ruby on Rails ActiveSupport::Concern 特性时如何“嵌​​套”包含模块的问题之后,我想了解我应该在哪里声明通过包含“嵌套”模块来添加到类中的方法以使该类的这些实例方法。也就是说,我有以下内容:

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

应该def my_method ... end在“正文”/“上下文”/“范围”中说明MyModuleB还是应该在included do ... end块中说明?有什么区别,我应该从中得到什么?

4

1 回答 1

5

混合到一个类中的模块中的方法成为该类的实例方法。虽然将它们放在included块中可能会起作用,但没有必要这样做。通过扩展,这适用于模块,因为您可以包含ModuleBinModuleA并且它的所有实例方法都成为实例方法 on ModuleA,并且一旦ModuleA包含在 class 上Foo,它的所有实例方法(包括那些混合 from 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>
于 2012-10-28T16:45:33.093 回答