ActiveRecord是一種ORM
ORM(Object-Relational-Mapping)讓我們可以利用物件導向的概念來操作關聯式資料庫,不需要透過繁瑣的SQL語法就能達成同樣的效果,對於維護程式也是比較容易的。但根據 抽象滲漏法則 所述:所有重大的抽象機制在某種程式上都是有漏洞的。ActiveRecord簡化了我們操作SQL的方便性,但相對的其效率就不會比直接使用SQL來得高,且可能也有它所無法涵蓋的範圍,甚至是漏洞。但站在網頁開發的角度,能夠快速建立網頁app以及易於處理複雜機制才是比較首要的,因此使用rails所提供的各種便利確實有其必要性。但永遠要記得,「唯一能適當處理漏洞的方法,就是弄懂該抽象原理以及所隱藏的東西。」
ActiveRecord將Ruby物件導向的概念套用到資料庫上運作,以下是其對應關係:
- class(a Model class) => table
- instances(a Model object) => rows
- attributes => columns
- class methods => operating the table
- instance methods => operating the row
關聯式資料庫基本操作
一對多關聯 one-to-many

以活動分類Category與活動Event來表示一對多關係。一個活動分類下可以有很多個活動,但一個活動只能被歸類在一個活動分類之下。
建立Model
1 | # 在Terminal運行 |
如此一來就建立了Event與Category兩個model,在Event內我們建立了category_id作為foriegn key,用來連接兩個Model。但目前為止,我們還沒定義出兩者的關聯,還需要在兩個model中加入一些設定:1
2
3
4
5
6
7class Category < ApplicationRecord
has_many :events # 記得要複數
end
class Event < ApplicationRecord
belongs_to :category, optional => true # 記得要單數
endhas_many表達了此Model有一對多關係,而belongs_to表達了此Model有多對一關係。
optional => true可以允許event沒有任何category的情況
建立Event物件
假設已經建立了2個Category,若要再建立幾個與Category相關的Event物件,可以有以下作法
- 建立Event物件,並關聯到Category
1
2
3
4
5
6a = Event.new(name: "BTD party", category: Category.first)
# 或是 a = Event.new(name: "BTD party", category_id: Category.first.id)
a.save
b = Event.create(name: "Picnic")
Category.first.events << b - 從Category中建立一個Event物件
1
2
3
4
5x = Category.first.events # 回傳一個Array
c = x.build(name: "KTV")
c.save
d = x.create(name: "Tennis game") # 不需再save查找物件
1
2
3
4
5x = Category.first
a = x.events.find(3) # 查詢第一個分類下的活動中的第三個
b = x.events.where(name: "KTV") # 1.查詢第一個分類中,叫作KTV的活動
# 2.回傳一個包含所有符合資格的資料的陣列,如果要找出其中的第一項,
# 就輸入 b[0]刪除物件
1
2
3x = Category.first
x.events.destroy_all # 一筆一筆刪除,並觸發每個event的destroy callback
x.events.delete_all # 一次刪除所有,不會觸發event的destroy callback
一對一關聯 one-to-one
上圖的例子為,一個活動會對應到一個場地,而在此我們限定一個場地只能辦一場活動,因此屬於一對一關係。
為什麼不把location列為Event的其中一個attribute就好?為什麼需要一對一關聯?
因為有些attribute可能並不是每個row都有,或是他只有在較少的情況需要被查詢,那麼我們就不需要找每筆資料時都一定要連這些attribute一起找出來,這時就可以考慮將他們列為一對一關聯。
建立Model
1 | # 在Terminal運行 |
Foriegn key要建立在哪一邊都可以。另外,一對一關聯同樣要建立關聯,才能在兩個Model之間心增一些方法來使用:1
2
3
4
5
6
7class Event < ApplicationRecord
has_one :location # 記得要單數
end
class Location < ApplicationRecord
belongs_to :event # 記得要單數
end
可以將一對一關聯視作一對多關聯的特例情況,所以新增、操作的方法都與一對多相同。
多對多關聯 many-to-many
一個活動可以有多位參加者,且一個參加者也能參與多項活動,此為多對多關係。多對多的情況,需要在中間建立一個join table,並將兩者的foriegn key建立在此join table內,專門負責處理兩項多對多資料的關聯。
建立Model
1 | # 在Terminal運行 |
再來是建立關聯1
2
3
4
5
6
7
8
9
10
11
12
13
14class Event < ApplicationRecord
has_many :event_attendees # 記得要複數
has_many :attendees, :through => :event_attendees
end
class EventAttendee < ApplicationRecord
belongs_to :event # 記得要單數
belongs_to :attendee # 記得要單數
end
class Attendee < ApplicationRecord
has_many :event_attendees # 記得要複數
has_many :events, :through => :event_attendees
end:through =>可以將兩個資料表建立起多對多關聯
操作
1 | # 先建立物件 |