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?

99封情书 提交于 2019-12-22 19:44:29

问题


I am using Ruby 1.9.2 and the Ruby on Rails v3.2.2 gem. After my previous question on how to “nest” the inclusion of modules when using the Ruby on Rails ActiveSupport::Concern feature, I would like to understand where I should state methods added to a class by including "nested" modules in order to make these instance methods of that class. That is, I have the following:

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

Should I state def my_method ... end in the "body" / "context" / "scope" of MyModuleB or I should state that in the included do ... end block? What is the difference and what I should expect from that?


回答1:


Methods in modules that get mixed into a class become instance methods on that class. While putting them in the included block would likely work, there's no need to do it. This, by extension, works with modules, since you can include ModuleB in ModuleA and all its instance methods become instance methods on ModuleA, and once ModuleA is included on class Foo, all its instance methods (including those mixed in from B) become instance methods on Foo.

A "traditional" mix-in looks like this:

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 just pretties this up a bit by automatically including a module named ClassMethods and by running the included block in the context of the including class, so the equivalent is:

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>


来源:https://stackoverflow.com/questions/13110749/how-to-make-methods-added-to-a-class-by-including-nested-modules-to-be-instanc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!