我的目标是在Rails的ActiveRecord中实现类似“has_many”的东西我想进一步了解类/对象是如何加载的。
当我在下面使用“has_many”时会发生什么?
class Widget < MiniRecord
has_many :trinkets
end
假设这是“miniRecord”的实现:
class MiniRecord
class << self
def has_many associated_model
@associations[:has_many] << associated_model_sym
end
end
def list_associations
do_stuff(@associations) # Where do I instantiate @associations?
end
end
我已经达到了它的工作点,但我有一些混乱的代码,我想削减。
我想了解这是如何工作的,但具体来说,我应该在哪里实例化@associations?
我希望能够在定义类时定义的
MiniRecord
的子类中“声明”属性(即静态变量),然后稍后对这些属性执行操作。 最佳答案
当您扩展MiniRecord
时,比如说MyRecord
,您会得到一个类层次结构图,如下所示(#SomeClass
是SomeClass
的特征类或单例类):
Class
|
MiniRecord --class--> #MiniRecord
| |
MyRecord --class--> #MyRecord
其中
list_associations
方法在MiniRecord
上定义,has_many
在#MiniRecord
上定义。当您在
has_many
的类体中调用MyRecord
时,它将首先在#MyRecord
中查找方法,这将失败然后它将在#MiniRecord
中查找并找到定义。如果它以某种方式失败,它将在Class
中查找定义这就是这种方法的工作原理。为了这个问题
具体来说,我应该在哪里实例化@associations?
你有两个选择:
使用时初始化
def has_many associated_model
@associations ||= Hash.new{|h, k| h[k] = [] }
@associations[:has_many] << associated_model_sym
end
创建子类时初始化
class MiniRecord
def self.inherited klass
klass.instance_variable_set(:@associations, Hash.new{|h, k| h[k] = [] }
end
end
请注意,不能直接访问实例方法中的
@associations
,因为它处于不同的作用域中您需要在list_associations
上显示@associations
,然后从中获取值。class MiniRecord
class << self
def has_many associated_model
@associations[:has_many] << associated_model
end
attr_reader :associations
end
def self.inherited klass
klass.instance_variable_set(:@associations, Hash.new{|h, k| h[k] = [] })
end
def list_associations
do_stuff(self.class.associations) # Where do I instantiate @associations?
end
def do_stuff sth
p sth
end
end
class MyRecord < MiniRecord
has_many :thrinks
end
r = MyRecord.new
r.list_associations
p MyRecord.associations