rails的orm很完善,可以非常方便的建立模型之间的关联.通过一些简单的代码实现一些常见的关联操作.
关联基础操作
最常见的关联方式就是一对多和一对一.实现的时候有两个基础的方法,has_many和belongs_to.根据字面上的意思理解,has_many表示拥有很多,belongs_to表示属于.
通过一个书籍和书籍分类的例子做一个总结
# 在app/models目录中生成相关的文件
rails g model book
rails g model type
修改数据库合并文件db/migrate,添加相关的字段
# book
class CreateBooks < ActiveRecord::Migration[5.1]
def change
create_table :books do |t|
t.string :title
t.string :description
t.text :content
t.integer :type_id # 关联types表
t.timestamps
end
end
end
# type
class CreateTypes < ActiveRecord::Migration[5.1]
def change
create_table :types do |t|
t.string :name
t.timestamps
end
end
end
修改书籍模型app/models/book.rb
class Book < ApplicationRecord
belongs_to :type
end
修改书籍分类app/models/type.rb
class Type < ApplicationRecord
has_many :books
end
创建一个实例
book = Book.create(title: '三国演义', description: '古典名著,中国四大名著之一') # 创建一个book实例
book.type.create(name: '古典名著') # 创建一个分类信息
# 通过type_id指定分类信息
shuihuzhuan = Book.create(title: '水浒传', description: '经典四大名著,105个男人和三个女人的故事',type_id: 1)
添加belongs_to之后,每一个模型的实例都将获得以下方法
# association
# 如果关联的对象存在就返回,否则为nil
# association=(associate)
# 设置关联对象
# build_association(attributes = {})
# 设置一个新的对象,根据传递的参数.临时存储,不保存数据库
# create_association(attributes = {})
# 设置新的关联对象,验证通过后存数据库
# create_association!(attributes = {})
# 设置新的关联对象,验证通过后存数据库.如果记录无效,会抛出异常
添加has_many之后实例获得以下方法
# collection
# collection<<(object, …​)
# collection.delete(object, …​)
# collection.destroy(object, …​)
# collection=(objects)
# collection_singular_ids
# collection_singular_ids=(ids)
# collection.clear
# collection.empty?
# collection.size
# collection.find(…​)
# collection.where(…​)
# collection.exists?(…​)
# collection.build(attributes = {}, …​)
# collection.create(attributes = {})
# collection.create!(attributes = {})
# 相关的方法都是一些集合的操作,具体的解释可以参考官网文档
多态关联
在实际开发中经常会遇到一个模型属于多个其他模型的情况.如:附件资源模型(存贮照片素材),可以属于用户和产品两个模型.用户有头像,产品有图片都可以存在资源表中,为了区分用户表和产品表的关联内容可以使用多态关联进行操作.
# 创建model
rails g model priture
rails g model user
rails g model product
修改数据库生成文件 db/migrate/xxx
# 创建用户表
class CreateUsers < ActiveRecord::Migration[5.1]
def change
create_table :users do |t|
t.string :name
t.timestamps
end
end
end
# 创建产品表
class CreateProducts < ActiveRecord::Migration[5.1]
def change
create_table :products do |t|
t.string :name
t.timestamps
end
end
end
# 创建图片资源表
class CreatePictures < ActiveRecord::Migration[5.1]
def change
create_table :pictures do |t|
t.string :path
t.string :name
t.integer :imageable_id
t.string :imageable_type
t.timestamps
end
add_index :pictures, [:imageable_type, :imageable_id]
end
end
class Picture < ApplicationRecord
belongs_to :imageable, polymorphic: true
end
class User < ApplicationRecord
has_many :pictures, as: :imageable
end
class Product < ApplicationRecord
has_many :pictures, as: :imageable
end
在belongs_to中通过设置polymorphic指定使用多态关联.在User实例上可以使用@user.pictures获取照片集合,在产品实例上使用@product.pictures获取.
当在执行数据创建方法之后,或分别在数据库中创建不同表关联的模型,根据imageable_type字段进行区分.字段存储的是关联的模型名字(User,Product)
可以测试刚才的数据是否可用
u = User.create(name: '小明') # 创建user
u.pictures.create(name: '头像', path: '/uploads/xm.jpg') # 创建picture
# 创建单个附件
p = Product.create(name: '华为mate10')
# 创建多个附件
p.pictures.create([
{ name: '主图', path: '/uploads/hw_main.png' },
{ name: '轮播1', path: '/uploads/hw_slider.png' },
{ name: '轮播', path: '/uploads/hw_slider2.png' },
])
网友评论