Rails中的has_many的运行流程是怎样的

2017-03-08  本文已影响238人  33d8e4ec2cc9

可参考https://ruby-china.org/topics/32419

屏幕快照 2017-03-08 下午1.29.34.png

整个方法就两行,几乎全部写在了Builder::HasMany这个类里面,继续点进去看

屏幕快照 2017-03-08 下午1.31.14.png

从这个方法来看,流程大致为创建reflection实例 -> 创建accessors方法 -> 创建回调方法 -> 创建验证方法 -> 创建扩展方法 -> 返回reflection实例
reflection实例用来干嘛?等会回来说

屏幕快照 2017-03-08 下午1.36.03.png

最主要的方法都在这里了

generated_association_methods这个方法要重点讲一讲

屏幕快照 2017-03-08 下午1.37.48.png

这个地方非常酷,方法并不是直接定义在本身的class中,而是创建一个常量到一个新module,然后include
ruby有个特性,就是你include module进来的时候,会复制一个Rclass结构体,但是它的方法表是指向原Rclass结构体的

所以你先include一个module进来,然后再改动这个module的方法,你的执行include的这个class也可以调用新生成的方法
这就是为什么可以先生成一个空的module,include进来以后再define属于这个module的方法
这样做可以让你自己在model定义同名方法,并使用default_scope调用原方法。

define_readers和define_writers分别创建读和写,但是这边我很奇怪,我传进来的参数去哪了,options并没有用在这两个方法里,于是我找到association这个方法

屏幕快照 2017-03-08 下午1.45.05.png

self.class._reflect_on_association(name)
这个就是比较厉害的地方了,从哪里取?回到一开始

Reflection.add_reflection self, name, reflection

真相大白了,reflection实例始终被保存在ActiveRecord::Reflection里面,也就是说我们使用has_many的时候,实际上是创建了Reflection实例,这个实例里面是我们传到has_many里面的参数,调用的时候吧实例丢过去当参数,当我们调用到方法的时候,实际上是先找到Reflection实例,再用这个实例做一系列的事情

屏幕快照 2017-03-08 下午1.50.47.png
上一篇下一篇

猜你喜欢

热点阅读