【问题标题】:Setting new class variables inside a module在模块内设置新的类变量
【发布时间】:2010-05-25 20:23:14
【问题描述】:

我有一个我一直在研究的插件,它将发布添加到 ActiveRecord 类。我像这样与出版商一起扩展我的课程:

class Note < ActiveRecord::Base
  # ...
  publishable :related_attributes => [:taggings]
end

我的发布者的结构如下:

module Publisher

  def self.included(base)
    base.send(:extend, ClassMethods)

    @@publishing_options = [] # does not seem to be available
  end

  module ClassMethods

    def publishable options={}
      include InstanceMethods

      @@publishing_options = options

      # does not work as class_variable_set is a private method
      # self.class_variable_set(:@@publishing_options, options)

      # results in: uninitialized class variable @@publishing_options in Publisher::ClassMethods
      puts "@@publishing_options: #{@@publishing_options.inspect}"

      # ...
    end

    # ...

  end

  module InstanceMethods

    # results in: uninitialized class variable @@publishing_options in Publisher::InstanceMethods
    def related_attributes
      @@publishing_options[:related_attributes]
    end

    # ...
  end

end

关于如何将选项传递给可发布并将它们作为类变量提供的任何想法?

【问题讨论】:

    标签: ruby class-variables


    【解决方案1】:

    我假设您想要每个班级一组publishing_options。在这种情况下,您只需在变量前面加上一个 @。请记住,类本身是类Class 的实例,因此当您处于类方法的上下文中时,您实际上希望在类上设置一个实例变量。类似于以下内容:

    module Publishable
      module ClassMethods
        def publishable(options)
          @publishing_options = options
        end
    
        def publishing_options
          @publishing_options
        end
      end
    
      def self.included(base)
        base.extend(ClassMethods)
      end
    end
    

    那么如果 ActiveRecord::Base 扩展如下:

    ActiveRecord::Base.send :include, Publishable
    

    你可以这样做:

    class Note < ActiveRecord::Base
      publishable :related_attributes => [:taggings]
    end
    
    class Other < ActiveRecord::Base
      publishable :related_attributes => [:other]
    end
    
    Note.publishing_options
    => {:related_attributes=>[:taggings]}
    
    Other.publishing_options
    => {:related_attributes=>[:other]}
    

    【讨论】:

    • 我不愿意使用实例变量来存储我的选项,但这对我有用。我想我只是在错误地思考当时正在创建哪个实例。在 InstanceMethods 模块中,我正在通过 self.class.publishing_options 访问发布选项 感谢您的快速回复
    • 是的,添加一个执行 self.class.publishing_options 的实例方法是使您的发布选项可用于 Note 的实例的方法
    • 五年后我才发现这个问题,它为我省去了几个小时的头痛 - 非常感谢@mikej!
    • 注意点:类实例变量不被继承。所以基本上这个的子类不会有这些可用的变量。当您调用某些超级方法并且该方法期望该变量的某些值时,这将导致问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 2017-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多