本站首页    管理页面    写新日志    退出


«October 2025»
1234
567891011
12131415161718
19202122232425
262728293031


公告
 本博客在此声明所有文章均为转摘,只做资料收集使用。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:1304
评论数量:2242
留言数量:5
访问次数:7628717
建立时间:2006年5月29日




[Ruby on Rails]has_many :through
软件技术

lhwork 发表于 2007/2/8 10:41:23

我已注意到使用 Rails 关联在创建多对多关系的两种方式上有些混乱。出现混乱是可以理解的,因为 has_many :through 还有些新,写它的文章并不多。 Has_and_belongs_to_many 出现的较早,确定的角色与资料超出了你为什么使用多对多关系的假设。事实上,许多人似乎并没有抓住本质上的区别。 就像我们从观看经典影片所学到的,告诉我们两个预期选择之间的区别最好方式是它们的舞蹈。你得观察每个人的表演。那么我们必须在两者之间选择哪个演员呢? 一、连接表:简单的关联 表: create_table "dancers_movies", :id => false do |t| t.column "dancer_id", :integer, :null => false t.column "movie_id", :integer, :null => false end 模型: class Dancer < ActiveRecord::Base has_and_belongs_to_many :movies end class Movie < ActiveRecord::Base has_and_belongs_to_many :dancers end has_and_belongs_to_many 关联的设置很简单。连接表只有被连接模型的外键,没有主键或其它属性。(其它属性使用暂时的 push_with_attributes 来支持,但该特征被废弃了。)此处没有给连接表使用的模型类。 二、连接模型:富关联(Rich Associations) 表: create_table "appearances", do |t| t.column "dancer_id", :integer, :null => false t.column "movie_id", :integer, :null => false t.column "character_name", :string t.column "dance_numbers", :integer end 模型: class Appearance < ActiveRecord::Base belongs_to :dancer belongs_to :movie end class Dancer < ActiveRecord::Base has_many :appearances, :dependent => true has_many :movies, :through => :appearances end class Movie < ActiveRecord::Base has_many :appearances, :dependent => true has_many :dancers, :through => :appearances end has_many :through 关联对这个简单例子来说很容易设定的,但是当使用其它特征如 polymorphism 时要有些技巧。用于连接模型的表有个主键并包含了类似其它模型的属性。 三、Checking out the moves 下面是对两种操作基本特征的比较 ----------------------------------------------------------------------------------- 关联 has_and_belongs_to_many has_many :through ---------------------------------------------------------------------------------- AKA habtm 关联 遍历关联 结构: 连接表(Join Table) 连接模型(Join Model) 主键: 无 有 富关联 否 是 代理集合 是 否 Distinct 选择 是 是 自引用 是 是 早期加载 是 是 多态性 否 是 多向连接 否 是 ------------------------------------------------------------------------------------------ 该表格内包含了很多东西,现在我们分别看一下: (1)、结构: has_and_belongs_to_many 使用了简单的连接表,表的每一行记录只有两个外键。没有为连接表使用模型类的连接记录从不会被直接访问。 has_many :through 更新连接表为一个完整的模型。它使用一个模型类来表现表内的条目。 (2)、主键: 连接表没有主键。我听说一些人,如从外键对创建一个主键,但 Rails 从不为任何东西使用主键。我不能肯定你为什么要得到创建的主键,虽然它可能依据你数据库给你一些性能上的好处。 (我不是一个 DBA ,所以对于主键不想说得太多。) 连接模型有键,就像其它模型。这意味着你可以直接地访问及管理记录。 (3)富关联: 在 Rails 1.1 以前,你使用 push_with_attributes 来存储额外的属性到你的 habtm 连接表内。这样做会带来很多问题,包括随后不能更新属性。Push_with_attributes 现在不再使用了。如果你希望一个带有额外属性的富关联的话,使用连接模型。 (4)、代理集合: 使用 habtm 的一个好处是,关联是个代理集合。这意味着你可以使用关联的 << 方法在连接表内创建条目,就像 has_many 关联。因为连接模型记录有这些额外属性,所以用同样方式来自动创建连接表条目会更复杂。所以你必须手工创建连接模型条目。(更完整的解释,可参阅我的 Why aren't join models proxy collections? 文章。) (5)、Distinct 选择: 有时候,连接表(或模型)在同样的记录之间可能有多个引用。例如,一个人可能是一本书的作者及插图绘制者。如果你有多个引用,数据库会返回给你所有与你查询相关多条记录。选项 :uniq 告诉关联过滤重复的对象,以便你只得到每个记录的一条显示。这类似于在 SQL 中使用 DISTINCT 关键字,但这是在 Ruby 内而不是数据库内移除重复发生的记录。这篇文章原只由 habtm 支持的 :uniq 才能查到,但现在通过 through 关联也可以查到。 (6)、自引用: Habtm 与 through 关联都可是自引用的。Users 的朋友用户就是一个自引用关系的例子。你可以通过在关联上使用带有 :foreign_key 与 :association_foreign_key 选项的 habtm 来完成。同样也可以使用 through 关联,因为它的做法不太明显,所以稍后我会写出如何处理它。 (7)、早期加载 Habtm 与 through 关联都通过 :include 选项来支持被关联对象的早期加载。 (8)、多态性: 连接模型与 through 关联可以用 polymorphic 模型类型工作。 (9)、多向连接 一个 habtm 关联只可以连接两个模型。但有时候你需要表现多个模型的关联。例如登记的可能是一位飞行家,一个乘客,及一个座位的分配。使用 through 关联,你可以创建一个连接模型,它连接你需要的多个模型。技巧部分是如何构建可方便地得到被关联对象的查询。 四、And the winner is... has_and_belongs_to_many 的使用范围狭小。但 has_many :through 则很广泛。 Seriously, there's no way to pick a winner here. Like any engineering decision, choosing a join table or a join model is a matter of picking the right tool for the job (or the right dancer for the part). Now that you've seen our players go head to head, you can make a better choice about who should get that part. 五、回帖部分: 1、David on 2006年4月21日 关于 distinct 选择 ---- 我认为你可以附加 :select 'DISTINCT *' 给关联,类似于: has_many foos, :through => bars, :select 'DISTINCT *' http://blog.hasmanythrough.com/articles/2006/04/20/many-to-many-dance-off


阅读全文(5245) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.376 second(s), page refreshed 144784150 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号