【问题标题】: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>
    

    【讨论】:

      猜你喜欢
      • 2012-10-18
      • 2014-01-26
      • 2013-05-26
      • 2014-04-28
      • 2015-03-28
      • 1970-01-01
      • 2013-11-02
      • 2013-09-05
      • 1970-01-01
      相关资源
      最近更新 更多