我想知道如何从模块中访问类变量
module Entity
def foo
# puts @@rules
end
end
class Person
include Entity
attr_accessor :id, :name
@@rules = [[:id, :int, :not_null],
[:name, :string, :not_null]]
end
class Car
include Entity
attr_accessor :id, :year
@@rules = [[:id, :string, :not_null],
[:year:, :int, :not_null]]
end
p = Person.new
c = Car.new
p.foo # [[:id, :int, :not_null], [:name, :string, :not_null]]
c.foo # [[:id, :string, :not_null], [:year, :int, :not_null]]
Run Code Online (Sandbox Code Playgroud)
我看了看cattr_accessor,并mattr_accessor从ActiveSupport,但仍无法找到一个方法来解决这个问题.
Max*_*Max 12
Ruby中的类变量在继承方面很奇怪.除非你确切地知道你在那里弄乱了什么,否则最好避免它们.在这种情况下,您可能认为您没有使用继承,但include实际上做的是插入Entity到祖先的中Person.看到:
Person.ancestors
# [Person, Entity, Object, Kernel, BasicObject]
Run Code Online (Sandbox Code Playgroud)
具体的行为是棘手的描述,但短期的版本是,基本上@@rules之间共享Entity,Person,和 Car!看:
Entity.class_variable_set(:@@rules, 'foo')
puts Car.class_variable_get(:@@rules)
# foo
puts Person.class_variable_get(:@@rules)
# foo
Run Code Online (Sandbox Code Playgroud)
你可能不想那样!
最好在这里使用一个类实例变量,实际上每个类都是独立的.
module Entity
# create the class instance variable methods when this is included
def self.included klass
klass.singleton_class.send(:attr_reader, :rules)
end
def foo
puts self.class.rules
end
end
class Person
include Entity
attr_accessor :id, :name
@rules = [[:id, :int, :not_null],
[:name, :string, :not_null]]
end
class Car
include Entity
attr_accessor :id, :year
@rules = [[:id, :string, :not_null],
[:year, :int, :not_null]]
end
Run Code Online (Sandbox Code Playgroud)
这不是最优雅的解决方案,但class_eval有效:
module Entity
def foo
self.class.class_eval('@@rules')
end
end
Run Code Online (Sandbox Code Playgroud)
编辑:实际上稍微干净一点可能是使用class_variable_get
module Entity
def foo
self.class.class_variable_get(:@@rules)
end
end
Run Code Online (Sandbox Code Playgroud)