我的目标是在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,您会得到一个类层次结构图,如下所示(#SomeClassSomeClass的特征类或单例类):

                             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

08-27 17:11