[Rails] Active Record Association (Model)
速查
- Book
belongs_to
Author: Book 會多 author_id - Supplier
has_one
Account: Account 會多 supplier_id
# 會產生 store_id 和 product_id
$ rails g model WareHouse store:references product:references
有 column_id 的 table 表示在比較下階。
觀念
在處理關連性資料庫時,我們經常需要透過 Query 的方式找出 另一個關連的資料。但是透過 Active Record Association,我們可以更方便的去操作關連性資料庫。
在 Rails 裡所謂的關係,是指在 Model 層級的關係,主要是透過 Model 的方法(例如 has_many
或 belongs_to
)搭配 Rails 的資料表慣例設定主鍵(Primary Key)及外部鍵(Foreign Key),讓這些資料表串在一起。
每一個 association 使用後對應會產生的方法:
- Detailed Association Reference @ RailsGuides
- Active Record Association @ RailsGuides
Generator
# rails g model [ModelClassName <column:type:options>
rails g model WareHouse store:references product:references
rails g model user email:index location_id:integer:index
- 最後加上
--skip-migration
將不會產生 migration 檔。 column:type:option
,options 可以加入index
這裡的 store:references
寫法其實也可以用前面的 store_id:integer
寫法,但 references 的寫法會多做幾件事:
- 自動加上索引(index),加快查詢速度。
- 自動幫 Model 加上
belongs_to
。
column options
index
unique
column type
integer
primary_key
decimal
float
boolean
binary
string
text
date
time
datetime
timestamp
參考範例
##
# price 要記得加上引號
##
rails g model user pseudo:string{30}
rails g model product 'price:decimal{10,2}'
# uniq, references, index
rails g model user email:index location_id:integer:index
rails g model user pseudo:string:uniq
rails g model user username:string{30}:uniq
rails g model photo album:references
rails g model WareHouse store:references product:references
# polymorphic
rails g model product supplier:references{polymorphic}
rails g model product supplier:references{polymorphic}:index
Advanced Rails model generator @ BY ANDREY KOLESHKO
關連類型
- belongs_to
- has_one
- has_many
- has_many :through
- has_one :through
- has_and_belongs_to_many
在使用上面這些 Active Record Association 的方法時, Database 的資料表和欄位必須透過
migration
或model
的 generator 先建立好。
一對一對應關係
keywords: belongs_to
, has_one
一對一的對應關係在使用時 AAA 會 belongs_to
BBB;而 BBB 則會 has_one
AAA,這兩者的差別在於要把 foreign_key 放在誰身上。當使用 AAA belongs_to BBB 時,AAA 的資料表中會多出 bbb_id。
但更重要的是透過資料實際的意義來思考,舉例來說應該是 User 擁有(has_one)Account,而非帳號擁有使用者;Account 應該是屬於(belongs_to)User 的,這時候 accounts 資料表中會多出一個 user_id 的 foreign_key
欄位。
過去在建立 migration 檔案時,會直接使用
t.integer :user_id
現在則可以使用t.references :user
,兩個意思是一樣的。
belongs_to
假設我們有 Author
和 Book
兩個 Model,其中每本書都會對應到一個作者(資料表和欄位需要先透過 migration 或 model generator 建立),那麼我們可以用 belongs_to
建立一對一的關連性關係:
# ./app/models/book.rb
class Book < ApplicationRecord
belongs_to :author
end
在 Book
資料表中會多一個 author_id
的欄位,用來對應到 Author
的 id
,這個 author_id 被用來做外部對應的欄位,稱為外部鍵(foreign key)
。
*Book belongs to Author- 表示,要在 migration 時 Book 資料表中會多出 author_id 的欄位。
belongs_to 在使用時要用單數。
migration 檔內容
相對應的 migration 檔會長這樣:
# ./db/migrate/migration_file.rb
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, index: true
t.datetime :published_at
t.timestamps
end
end
end
使用 :association, association=
keywords
:association
,association=(associate)
,build_association(attributes = {})
,create_association(attributes = {})
,create_association!(attributes = {})
association 就是 belongs_to 後面方的 Symbol,因此當加上 belongs_to :author
之後,Book Model 會動態的多了幾個好用的方法,像是 :author
, author=
:
# rails console
# :author 方法
book = Book.first
book.author # 列出屬於該本書的 author 實例物件
# author= 方法
aaron = Author.find(1)
book.author = aaron # = 後面要放 Model 的實例物件
has_one
Supplier has one Account 表示要在 migration 時,Account 資料表中會多出 supplier_id 的欄位。
# ./app/models/supplier.rb
class Supplier < ApplicationRecord
has_one :account
end
migration 檔案內容
其中相對應的 migration 檔會長這樣,資料表在建立的時候一樣試用 account belongs_to supplier
:
# ./db/migrate/migration_file.rb
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, index: { unique: true }, foreign_key: true # 表示 supplier 是 foreign key
t.string :account_number
t.timestamps
end
end
end