Использование @@
переменных экземпляра класса нерегулярно, а число случаев, когда они строго необходимы, чрезвычайно редко. Большую часть времени они просто вызывают проблемы или путаницу. Как правило, вы можете использовать обычные переменные экземпляра в контексте класса без проблем.
Что вы можете сделать, это использовать другой шаблон для такого рода вещей. Если у вас есть mattr_accessor
, предоставляемый ActiveSupport, вы можете использовать его вместо этой переменной, или вы всегда можете написать свой собственный эквивалент в компоненте ClassMethods
.
Один из подходов, которые я использовал, состоит в том, чтобы разбить ваше расширение на два модуля: хук и реализацию. Хук добавляет только методы к базовому классу, которые могут использоваться для добавления остальных методов, если это необходимо, но в противном случае не загрязняет пространство имен:
module ClassExtender
def self.included(base)
base.send(:extend, self)
end
def engage(options = { })
extend ClassExtenderMethods::ClassMethods
include ClassExtenderMethods::InstanceMethods
self.class_extender_options.merge!(options)
end
end
Этот метод engage
можно вызывать как угодно, как в вашем примере это auditable
.
Затем вы создаете контейнерный модуль для методов класса и экземпляра, которые расширение добавляет, когда оно выполняется:
module ClassExtenderMethods
module ClassMethods
def class_extender_options
@class_extender_options ||= {
:default_false => false
}
end
end
module InstanceMethods
def instance_method_example
:example
end
end
end
В этом случае существует простой метод class_extender_options
, который можно использовать для запроса или изменения параметров для определенного класса. Это избавляет от необходимости использовать переменную экземпляра напрямую. Также добавлен пример метода экземпляра.
Вы можете определить простой пример:
class Foo
include ClassExtender
engage(:true => true)
end
Затем проверьте, что он работает правильно:
Foo.class_extender_options
# => {:default_false=>false, :true=>true}
foo = Foo.new
foo.instance_method_example
# => :example