http://guides.rubyonrails.org/association_basics.html
1、为什么要关联?
为什么我们需要在两个model之间建立关联?因为它让通用操作变得简单和容易。例如,考虑有一个rails应用程序包含一个customer model和一个order model。每一个customer有很多的order。没有关联时,model声明如下:
class Customer < ActiveRecord::Base
end
class Order < ActiveRecord::Base
end
现在,假设我们想为一个已存在的客户添加一个新的订单,我们需要像这样做:
@order = Order.create(:order_date => Time.now, :customer_id => @customer.id)
再考虑在删除一个客户时,确保他的订单也被删除了。
@orders = Order.find_by_customer_id(@customer.id)
@orders.each do |order|
order.destroy
end
@customer.destroy
使用Active Record关联,我们通过声明告诉Rails在这两个model之间存在的关联使这些及其他一些操作流线化,这里是建立customer model和order model的改进代码
class Customer < ActiveRecord::Base
has_many :orders, :dependent => :destroy
end
class Order < ActiveRecord::Base
belongs_to :customer
end
有了这些改变,很容易实现为一个特定的客户创建一个订单
@order = @customer.orders.create(:order_date => Time.now)
删除一个客户和它的订单则更加容易
@customer.destroy
欲学习更多不同类型的关联,阅读本手册的下一节。
下一节内容有关使用关联的一些建议和戏法,
以及一份完整的有关rails中关联的方法、选项的参考。
2、关联类型
在Rails中,关联是两个Active Record Model之间的连接,关联通过macro-style的调用来实现的,因此你可以声明来添加特性到你的model。例如,通过声明一个model belongs_to另一个,你的Rails指令去维护在两个model的实例之间的Primay-Key_Foreign Key信息,然后你同时有许多有用的方法添加到了你的model中。Rails支持六种类型的关联:
- belongs_to 从属关系
- has_one 拥有(一对一)
- has_many 拥有(一对多)
- has_many :through 一对多,通过中间关联
- has_one :through 一对一,通过中间关联
- has_and_belongs_to_many 多对多
在本手册的剩下部分,你将会学到如何声明和使用各种形式的关联。但首先,快速的介绍下每一种关联类型的情况是必要的。
2.1、belongs_to关联
belongs_to关联与另一个model建立一对一联系,这样子声明的模型的每一个实例belongs_to其他模型的一个实例。例如,如果你的应用程序包含客户和订单,且每一个订单会被精确的分配给一个客户,你可像这样声明这个订单model:
class Order < ActiveRecord::Base
belongs_to :customer
end
2.2、has_one关联
has_one关联同样是与另一个model建立一对一关联,但语义上有些不同(还有结果)。这种关联表明每一个model实例包含或者持有另一个model的实例。例如,如果你的应用程序里的每一个供应商仅拥有一个账号,你可像这样声明供应商model:
class Supplier < ActiveRecord::Base
has_one :account
end
2.3、has_many关联
has_many关联表明与另一个model的一对多关系。你会经常在belongs_to关系的“另一边”找到这种关系。这种关系表明这种model的每个实例拥有0或多个的另一个model的实例。例如,在一个应用程序里包含客户和订单,客户model可以这样声明:
class Customer < ActiveRecord::Base
has_many :orders
end
2.4、has_many :through关联
has_many :through关联通常用于和另一个model建立多对多关联。
这种关系表明这样声明的model可以通过through处理匹配0或多个另一个model的实例。例如,考虑一个有关病人预约内科医生的医学练习,相关的声明可能像这样:
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, :through => :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, :through => :appointments
end
has_many :through关联同样有益于建立"快捷方式"通过嵌套的has_many关联。例如,如果一个文章有多个章节,而每个章节有很多段落,你也许有时想得到一个文档中所有段落的简单集合。你可以这种方式设置:
class Document < ActiveRecord::Base
has_many :sections
has_many :paragraphs, :through => :sections
end
class Section < ActiveRecord::Base
belongs_to :document
has_many :paragraphs
end
class Paragraph < ActiveRecord::Base
belongs_to :section
end
2.5、has_one :through关联