Установка новых переменных класса внутри модуля - PullRequest
4 голосов
/ 26 мая 2010

У меня есть плагин, над которым я работаю, который добавляет публикацию в классы 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

Есть какие-нибудь идеи о том, как передать параметры в публикуемые и сделать их доступными в качестве переменной класса?

1 Ответ

16 голосов
/ 26 мая 2010

Я предполагаю, что вы хотите один набор 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]}
...