如何在 class 和 class 实例之间共享数据 Ruby

How to share data between class and class instance in Ruby

为了在 class 和 class 实例之间共享数据,ActiveSupport 有很棒的方法 class_attribute。例如

require 'active_support/core_ext/class/attribute.rb'

# Step 1: declare a class record and implement class_attribute :fields.
# We can use it to declare attr_accessor
class Record
  class_attribute :fields
  self.fields = [:id]

  def self.attribute(new_field_name)
    self.fields = fields | [new_field_name]

    instance_eval do
      attr_accessor new_field_name
    end
  end
end

# Step 2: Declare class Topic with two attributes
class Topic < Record
  attribute :title
  attribute :body
end

# Step 3: Declare another class user with other two attributes
# And one more class with addition attribute
class User < Record
  attribute :first_name
  attribute :last_name
end


# Step 4: Let's check.
# Each class has it own attributes and data is shared between class and instances
puts Topic.fields
# [:id, :title, :body]
puts Topic.new.fields
# [:id, :title, :body]

puts User.fields
# [:id, :first_name, :last_name]
puts User.new.fields
# [:id, :first_name, :last_name]

我写了一点 ruby 脚本,不想对 ActiveSupport 有额外的依赖。此外,我不能使用 class 变量(带有“@@”的变量),因为更改子 class 上的值会影响父 class.

作为选项 - 我可以将 class_attribute 源代码复制并粘贴到我的 Ruby-脚本中,但我很想在纯 Ruby [=15 中找到解决方案=]

没有人可以帮助我或给我建议如何在纯 Ruby 上轻松实现它吗?

也许为 class 实例变量定义一个 attr_accessor,然后将所需的实例方法转发给 class 上的那些方法?

require 'forwardable'

class Foo
  extend Forwardable

  class << self
    attr_accessor :fields
  end

  def_delegator self, :fields
  def_delegator self, :fields=
end

foo = Foo.new

p Foo.fields #=> nil
p foo.fields #=> nil

Foo.fields = { set_on: 'Class' }
p foo.fields #=> {:set_on=>"Class"}

foo.fields = { set_on: 'instance' }
p Foo.fields #=> {:set_on=>"instance"}