Rails 支持六种关联:
belongs_tohas_onehas_manyhas_many :throughhas_one :throughhas_and_belongs_to_many
class Author < ActiveRecord::Base
attr_accessible :name
has_many :books
end
class Book < ActiveRecord::Base
attr_accessible :name, :author_id
belongs_to :writer, class_name: 'Author', foreign_key: 'author_id'
end
has_many :through 关联
has_many :through 关联经常用于建立两个模型之间的多对多关联。这种关联表示一个模型的实例可以借由第三个模型,拥有零个和多个另一模型的实例。例如,在医疗锻炼中,病人要和医生约定练习时间。这中间的关联声明如下:
|
has_many :through 还能简化嵌套的 has_many 关联。例如,一个文档分为多个部分,每一部分又有多个段落,如果想使用简单的方式获取文档中的所有段落,可以这么做:
|
加上 through: :sections 后,Rails 就能理解这段代码:
@document.paragraphs多态关联
关联还有一种高级形式——多态关联(polymorphic association)。在多态关联中,在同一个关联中,一个模型可以属于多个模型。例如,图片模型可以属于雇员模型或者产品模型,模型的定义如下:
|
在 belongs_to 中指定使用多态,可以理解成创建了一个接口,可供任何一个模型使用。在 Employee 模型实例上,可以使用
@employee.pictures 获取图片集合。
类似地,可使用 @product.pictures 获取产品的图片。
在 Picture 模型的实例上,可以使用 @picture.imageable 获取父对象。不过事先要在声明多态接口的模型中创建外键字段和类型字段:
|
控制缓存
关联添加的方法都会使用缓存,记录最近一次查询的结果,以备后用。缓存还会在方法之间共享。例如:
author.books
# 从数据库中检索图书author.books.size
# 使用缓存的图书副本author.books.empty?
# 使用缓存的图书副本 |
应用的其他部分可能会修改数据,那么应该怎么重载缓存呢?在关联上调用 reload 即可:
author.books
# 从数据库中检索图书author.books.size
# 使用缓存的图书副本author.books.reload.empty?
# 丢掉缓存的图书副本 # 重新从数据库中检索 |
Active Record 提供了 :inverse_of 选项,可以通过它明确声明双向关联:
class
Author < ApplicationRecord has_many
:books, inverse_of:
'writer'endclass
Book < ApplicationRecord belongs_to
:writer, class_name:
'Author', foreign_key:
'author_id'end
inverse_of 有些限制:
- 不支持
:through关联; - 不支持
:polymorphic关联; - 不支持
:as选项;
class_name
如果另一个模型无法从关联的名称获取,可以使用 :class_name 选项指定模型名。例如,如果一本书属于一位作者,但是表示作者的模型是
Patron,就可以这样声明关联:
class
Book < ApplicationRecord belongs_to
:author, class_name:
"Patron"end |
foreign_key
按照约定,用来存储外键的字段名是关联名后加 _id。:foreign_key 选项可以设置要使用的外键名:
class
Book < ApplicationRecord belongs_to
:author, class_name:
"Patron", foreign_key:
"patron_id"end |
primary_key
按照约定,Rails 假定使用表中的 id 列保存主键。使用 :primary_key 选项可以指定使用其他列。
假如有个 users 表使用 guid 列存储主键,todos 想在
guid 列中存储用户的 ID,那么可以使用 primary_key 选项设置:
class
User < ApplicationRecord self.primary_key =
'guid' # 主键是 guid,不是 idendclass
Todo < ApplicationRecord belongs_to
:user, primary_key:
'guid'end |
执行 @user.todos.create 时,@todo 记录的用户 ID 是 @user 的
guid 值。
touch
如果把 :touch 选项设为 true,保存或销毁对象时,关联对象的 updated_at 或
updated_on 字段会自动设为当前时间。
class
Book < ApplicationRecord belongs_to
:author, touch:
trueendclass
Author < ApplicationRecord has_many
:booksend |
includes
如果经常要直接从商品上获取作者对象(@line_item.book.author),就可以在关联中把作者从商品引入图书中:
class
LineItem < ApplicationRecord belongs_to
:book, -> { includes
:author }endclass
Book < ApplicationRecord belongs_to
:author has_many
:line_itemsendclass
Author < ApplicationRecord has_many
:booksend每个 模型实例 都获得了这些方法:
assembliesassemblies<<(object, ...)assemblies.delete(object, ...)assemblies.destroy(object, ...)assemblies=(objects)assembly_idsassembly_ids=(ids)assemblies.clearassemblies.empty?assemblies.sizeassemblies.find(...)assemblies.where(...)assemblies.exists?(...)assemblies.build(attributes = {}, ...)assemblies.create(attributes = {})assemblies.create!(attributes = {})
本文深入解析了Rails中的六种模型关联方式,包括belongs_to、has_one、has_many等,并详细介绍了多态关联、缓存控制及高级配置选项如inverse_of、class_name等。
&spm=1001.2101.3001.5002&articleId=77836180&d=1&t=3&u=beba41394ac346e79af39376d6229bec)
653

被折叠的 条评论
为什么被折叠?



