How to “nest” the inclusion of modules when using the Ruby on Rails ActiveSupport::Concern feature?

前端 未结 1 1177
情深已故
情深已故 2021-02-09 07:33

I am using Ruby 1.9.2 and the Ruby on Rails v3.2.2 gem. I would like to \"nest\" the inclusion of modules given I am using the RoR ActiveSupport::Concern feature, but I have a d

相关标签:
1条回答
  • If you include MyModuleB in the "body" of MyModuleA, then it is the module itself that is extended with B's functionality. If you include it in the included block, then it is included on the class that mixes in MyModuleA.

    That is:

    module MyModuleA
      extend ActiveSupport::Concern
      include MyModuleB
    end
    

    produces something like:

    MyModuleA.send :include, MyModuleB
    class Foo
      include MyModuleA
    end
    

    while

    module MyModuleA
      extend ActiveSupport::Concern
      included do
        include MyModuleB
      end
    end
    

    produces something like:

    class Foo
      include MyModuleA
      include MyModuleB
    end
    

    The reason for this is that ActiveSupport::Concern::included is analogous to:

    def MyModuleA
      def self.included(klass, &block)
        klass.instance_eval(&block)
      end
    end
    

    The code in the included block is run in the context of the including class, rather than the context of the module. Thus, if MyModuleB needs access to the class it's being mixed-in to, then you'd want to run it in the included block. Otherwise, it's effectively the same thing.

    By means of demonstration:

    module A
      def self.included(other)
        other.send :include, B
      end
    end
    
    module B
      def self.included(other)
        puts "B was included on #{other.inspect}"
      end
    end
    
    module C
      include B
    end
    
    class Foo
      include A
    end
    
    # Output:
    # B was included on C
    # B was included on Foo
    
    0 讨论(0)
提交回复
热议问题