如何在 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"}
为了在 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"}