如何在 Ruby 中最好地抽象 class 变量

How to best abstract class variables in Ruby

我有一个class比如

# this has been simplified for the example
class MyClass
  @@private_attributes = []

  def self.private_attributes(*args)
    @@private_attributes = args
  end

  def private_attributes
    @private_attributes ||= @@private_attributes
  end
end

效果很好。我将此 @@private_attributes 设置为 class 级别,然后以多种方式在实例级别使用。

我想在其他地方抽象这个逻辑来简化我的 class,类似的东西

class MyClass
  include PrivateAttributes
end

当我创建模块 PrivateAttributes 时,无论我如何塑造它,@@private_attributesMyClass 级别都无法理解。

我尝试了很多东西,但这是最新的代码尝试

module PrivateAttributes
  include ProcessAttributes

  def self.included(base)
    base.extend(ClassMethods)
    base.include(InstanceMethods)
  end

  module ClassMethods
    @@private_attributes = []

    def private_attributes(*args)
      @@private_attributes = args
    end
  end

  module InstanceMethods
    def private_attributes
      @private_attributes ||= process_attributes_from(@@private_attributes)
    end

    def private_attributes?
      instance_options[:scope] == :private
    end
  end
end

它因这个错误而崩溃

 NameError:
   uninitialized class variable @@private_attributes in PrivateAttributes::InstanceMethods
   Did you mean?  private_constant

简而言之,@@private_attributes并没有在整个代码中传递,而是停留在模块级别。

从我原来的 class 中抽象出这个逻辑的最佳方式是什么?

工作解决方案

一个简单的解决方法是在 class 级别上使用 mattr_accessor 或任何类似的东西来传达我们的数据。在这种情况下,我更愿意写下我自己的方法:

module PrivateAttributes
  include ProcessAttributes

  def self.included(base)
    base.extend(ClassMethods)
    base.include(InstanceMethods)
  end

  module ClassMethods
    @@private_attributes_memory = []

    def private_attributes(*args)
      @@private_attributes_memory = args
    end

    def private_attributes_memory
      @@private_attributes_memory
    end
  end

  module InstanceMethods
    def private_attributes
      @private_attributes ||= process_attributes_from private_attributes_memory
    end

    # you can add diverse methods here
    # which will be used in MyClass once included

    private

    def private_attributes_memory
      self.class.private_attributes_memory
    end
  end
end