Rails 的 Active Record Associations是一个神奇的魔法,如果你的数据模型设计合理,再结合该魔法,你将避免大量的代码并且代码的逻辑性更强更易读懂。下面将介绍如何使用这个魔法。
Active Record Associations 需要依靠有下面六种的方法来施展魔法:
belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many
下面介绍六种方法可以组成不同的“模型关系”:
1. The belongs_to
Association
一本书属于一个作者
类:
class Book < ApplicationRecord
belongs_to :author
end
class Author < ApplicationRecord
end
迁移类:
class CreateBooks < ActiveRecord::Migration[5.0]
def change
create_table :authors do |t|
t.string :name
t.timestamps
end
create_table :books do |t|
t.belongs_to :author
t.datetime :published_at
t.timestamps
end
end
end
2.The has_one
Association
一个供应商有且只有一个账户
类:
class Supplier < ApplicationRecord
has_one :account
end
迁移类:
class CreateSuppliers < ActiveRecord::Migration[5.0]
def change
create_table :suppliers do |t|
t.string :name
t.timestamps
end
create_table :accounts do |t|
t.belongs_to :supplier
t.string :account_number
t.timestamps
end
end
end
#在账户表中创建唯索引和外键
create_table :accounts do |t|
t.belongs_to :supplier, index: { unique: true }, foreign_key: true
# ...
end
3 . The has_many
Association
一个作者可以写多本书:
类
class Author < ApplicationRecord
has_many :books
end
迁移类
class CreateAuthors < ActiveRecord::Migration[5.0]
def change
create_table :authors do |t|
t.string :name
t.timestamps
end
create_table :books do |t|
t.belongs_to :author
t.datetime :published_at
t.timestamps
end
end
end
4. The has_many :through
Association
一个医生可以对多个病人,一个病人可以对多个医生
类:
class Physician < ApplicationRecord
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ApplicationRecord
belongs_to :physician
belongs_to :patient
end
class Patient < ApplicationRecord
has_many :appointments
has_many :physicians, through: :appointments
end
迁移类:
class CreateAppointments < ActiveRecord::Migration[5.0]
def change
create_table :physicians do |t|
t.string :name
t.timestamps
end
create_table :patients do |t|
t.string :name
t.timestamps
end
create_table :appointments do |t|
t.belongs_to :physician
t.belongs_to :patient
t.datetime :appointment_date
t.timestamps
end
end
end
一个文档有很多节,而一个节有很多段落,则有时您可能希望获得文档中所有段落的简单集合
类:
class Document < ApplicationRecord
has_many :sections
has_many :paragraphs, through: :sections
end
class Section < ApplicationRecord
belongs_to :document
has_many :paragraphs
end
class Paragraph < ApplicationRecord
belongs_to :section
end
@document.paragraphs
5. The has_one :through
Association
一个供应商对应一个账户,一个账户对应一个账户历史
class Supplier < ApplicationRecord
has_one :account
has_one :account_history, through: :account
end
class Account < ApplicationRecord
belongs_to :supplier
has_one :account_history
end
class AccountHistory < ApplicationRecord
belongs_to :account
end
class CreateAccountHistories < ActiveRecord::Migration[5.0]
def change
create_table :suppliers do |t|
t.string :name
t.timestamps
end
create_table :accounts do |t|
t.belongs_to :supplier
t.string :account_number
t.timestamps
end
create_table :account_histories do |t|
t.belongs_to :account
t.integer :credit_rating
t.timestamps
end
end
end
6. The has_and_belongs_to_many
Association
多对多连接,而没有中间模型,这个和has_many :through 的区别是不用你再写中间模型,但是迁移文件里还是需要建表的。
类:
class Assembly < ApplicationRecord
has_and_belongs_to_many :parts
end
class Part < ApplicationRecord
has_and_belongs_to_many :assemblies
end
迁移类:
class CreateAssembliesAndParts < ActiveRecord::Migration[5.0]
def change
create_table :assemblies do |t|
t.string :name
t.timestamps
end
create_table :parts do |t|
t.string :part_number
t.timestamps
end
create_table :assemblies_parts, id: false do |t|
t.belongs_to :assembly
t.belongs_to :part
end
end
end
7.Polymorphic Associations
多态关联
8. Self Joins
在设计数据模型时,有时会发现一个与其自己关联的模型。 例如,您可能希望将所有员工存储在一个数据库模型中,但是能够跟踪经理和下属之间的关系。 这种情况可以用自我加入的关联来建模:
类:
class Employee < ApplicationRecord
has_many :subordinates, class_name: "Employee",
foreign_key: "manager_id"
belongs_to :manager, class_name: "Employee", optional: true
end
迁移类:
class CreateEmployees < ActiveRecord::Migration[5.0]
def change
create_table :employees do |t|
t.references :manager
t.timestamps
end
end
end