Ruby on Rails中的has_many(以及类似的方法)是如何实现的?

8
我正在分析Rails源代码,因为我想了解has_many和类似结构的内部工作原理。
到目前为止,我已经找到了方法的实现位置(GitHub链接):它在ActiveRecord :: Associations模块中。
def has_many(name, options = {}, &extension)
  Builder::HasMany.build(self, name, options, &extension)
end

这个最终以类ActiveRecord::Associations::Builder::CollectionAssociation结束 (Github链接)

def self.build(model, name, options, &extension)
  new(model, name, options, &extension).build
end

这是我的Ruby技能的瓶颈,我无法继续跟进并找到“new”在哪里实现以及它的作用。希望有人能给出正确的方向,并解释一下其中的内部原理。

5
阅读您正在使用的工具源代码是为了更深入地了解其内部机制,这是一个明智的选择。加油! - s.m.
1
@s.m.:我同意。如果阅读源代码不算“显示研究努力”(正如点赞按钮的工具提示所说),那我不知道还有什么能算了!+1! - Jörg W Mittag
1
感谢大家的回答。我接受了Jörg的答案,因为它最为详细。同时也要给Baldrik和s.m.点个赞,因为他们是第一个回答的人。 - Tadej Mali
3个回答

4
基本上,new 是这样定义的:
class Class
  def new(*args, &block)
    obj = allocate

    obj.initialize(*args, &block)
    # *actually* obj.send(:initialize, *args, &block) since initialize is private

    obj
  end
end

allocate 的定义如下:

class Class
  def allocate
    # magic stuff for creating an empty object which cannot be expressed in Ruby:

    new_obj = Deep::Within::VM.__somehow_magically_allocate_memory__!

    new_obj.__class__ = self

    new_obj
  end
end

1

new 调用当前类的构造函数。构造函数是在 self.build 方法之后定义的 CollectionAssociation 类中的 initialize 方法。这是纯 Ruby (ruby guide)


1
进一步解释@Baldrick的答案,他是正确的,newClass中被定义为类方法和实例方法,因此对所有类都可用。 new的作用是调用allocateinitialize(假设已定义initialize方法)。

我认为new不是定义为类方法的。Class类是其本身的实例(耶,循环!),这就是为什么 Class.new 起作用的原因。 - Jörg W Mittag
@JörgWMittag 我并不是 Ruby 内部的专家,但文档显示 new 是 Class 的类方法和实例方法,如果我没记错的话。 - s.m.
实际上,这是Class#initialize的文档。RDoc只是将其显示Class::new的文档。它对于所有类都是这样做的,因为这是你通常使用 initialize方法的方式。你实际上不会调用它,而是让new来调用它。如果你查看源代码,你可以看到文档块位于rb_class_initialize函数之上,对应于Class#initialize方法。 - Jörg W Mittag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接