关于 inverse_of 的困惑与探究
来源:互联网 发布:highlight.js显示行号 编辑:程序博客网 时间:2024/05/17 01:06
最近在使用 关联 的时候,由于一点手误遇到了些问题,于是花了一下午时间来仔细读了 Guide 中关于 Active Record Associations 的部分。在看到 inverse_of
时,感觉自己突然一下就懵了。
问题缘由
我对 inverse_of
的困惑并不是在实际使用中产生的,即使不了解它也能在项目中愉快的玩耍,这似乎又旁证了 Rails 是一个很智能的框架。
不过它的 Guide 文档里这一部分就有些描述不清了(或说自相矛盾?)。关于 inverse_of
的功用倒是没有什么疑惑,只是被这混乱的文档弄得不知道哪些情况下需要去显式的声明 inverse_of
, 哪些情况下 inverse_of
又是无效果的。
问题描述
Guide 中关于 inverse_of
的解释:http://guides.rubyonrails.org/association_basics.html#bi-directional-associations
其中有两处说明让我很费解:
其一:
There are a few limitations to inverse_of support:
1. They do not work with :through associations.
2. They do not work with :polymorphic associations.
3. They do not work with :as associations.
4. For belongs_to associations, has_many inverse associations are ignored.
按第四条所说的,has_many 的关联是无效的,但是 Guide 中的栗子便是使用的 has_many, 而且很好的证明了 inverse_of 的效果。
【2016.6.17】 这个其实没有疑问,这是指在 has_many / belongs_to 关联的两端都声明 inverse_of,只会按 belongs_to 一方的声明处理
其二:
Every association will attempt to automatically find the inverse association and set the :inverse_of option heuristically (based on the association name). Most associations with standard names will be supported. However, associations that contain the following options will not have their inverses set automatically:
1. :conditions
2. :through
3. :polymorphic
4. :foreign_key
按这个说法,只要是按约定命名的 关联 会自动加上 inverse_of, 那么,演示用例是按约定命名的吧,也不属于下面声明的四种情况,为什么加与不加是有差别的?
【2016.6.17】 这个其实也没有疑问,这是因为 Rails 版本变迁,我当时看得文档没来得及更新导致的。文章后面部分已经解释了这个问题,这里提前把结论贴一下。
动手验证
验证环境 Rails 版本:4.2.1
定义模型:
# a.rbclass A < ActiveRecord::Base has_many :bend# b.rbclass B < ActiveRecord::Base belongs_to :aend
测试结果:
2.2.1 :001 > a = A.create :name => 'ichou' => #<A id: 2, name: "ichou", created_at: "2015-04-04 06:41:41", updated_at: "2015-04-04 06:41:41">2.2.1 :002 > b1 = B.create :name => 'kindle', :a => a => #<B id: 3, name: "kindle", a_id: 2, created_at: "2015-04-04 06:42:45", updated_at: "2015-04-04 06:42:45">2.2.1 :003 > b2 = B.create :name => 'Air', :a => a => #<B id: 4, name: "Air", a_id: 2, created_at: "2015-04-04 06:43:10", updated_at: "2015-04-04 06:43:10">2.2.1 :004 > a.name.object_id => 702646376541202.2.1 :005 > b1.a.name.object_id => 702646376541202.2.1 :006 > b2.a.name.object_id => 70264637654120
object_id 全都一样,说明 inverse_of
已经被启用了。事实上,即使严格按照 Guide 的案例来做,你也会发现结果全是 True,而不是 Guide 所说的结果。
结论:在 4.1+ 的 Rails 中,即使不手动声明 inverse_of
,has_many 关联也会自动创建,而且是有效的!
总结与使用
inverse_of
的作用在于关联模型间共用实例,而不是让不同的查询在内存中存在多份 Copies.
实际运用中可以带来两个好处,一是减少数据库查询;二是在对 关联对象 修改数据后写入数据前,保证从任何一方取得的值都是最新的。从 4.1 开始,基本的关联类型(has_many, has_one, belongs_to),若按约定命名,不需要再手动设定
inverse_of
(当时的)Guide 的相关用例是有问题的,或者说是适用于老版本的 Rails,而不是当前版本。
因为给basic associations\*
自动添加inverse_of
是在 Rails 4.1 加入的特性。
事实上,关于 has_many 的那个例子,在 4.1 及以后的版本中已经不能复现了。inverse_of
已经支持 has_many 是从 3.2.1 开始的,4.1 开始支持自动添加inverse_of
, 但是 has_many :through 仍然需要显式声明inverse_of
使用没有持久化的关联对象时,根据需要使用 inverse_of,否则反向调用会得到 nil 或者还未更新的 对象。详见topics/6426
感谢 社区 和 stackoverflow 上的大大们,感谢微信群 成都Ruby群 里的星哥。
比较新手向的帖子,若有纰漏,烦请指正
- 关于 inverse_of 的困惑与探究
- 关于Spring与hibernate整合的困惑
- 关于工作的困惑
- 关于WM_NOTIFY的困惑。
- 关于SWIFT的困惑
- 关于socket的困惑
- 关于C++的困惑
- 关于namespace的困惑
- 关于zeromemory函数 与ascii unicode的bug与困惑
- 关于Android URI 的一点困惑与解答
- 关于宗海图84与2000坐标差别的困惑
- 一个常见REST应用场景的困惑和探究
- 关于学习语言的困惑!
- 关于'`global namespace''的困惑
- 关于学习JAVA的困惑。
- 关于GDI画图的困惑
- 关于recv的一点困惑
- 关于结构体的困惑
- AB 模拟测试秒杀
- 进制转换,计算 还有各种数据类型和字符
- hdu4632(区间dp+容斥)
- mashenday03
- 实习小记一:RESTful架构理解入门
- 关于 inverse_of 的困惑与探究
- Minimum Path Sum
- QGroupBox QToolBox QComboBox
- Java学习之对象与对象引用的区别
- LintCode之比较字符串
- 数据库一系列查询函数
- 开源系统管理资源大合辑
- Maximum Subarray
- java基础primitive 类型