想好好學會 rails,不得不好好認識相當重要的關聯性,能夠理解並善用的話,你就能在各個 model 之間進行資料庫的溝通,拿到你想要的資料。

Model 關聯性

Rails 的 Model 關聯主要有三種類型

  • 一對一 (1:1)
  • 一對多 (1:N)
  • 多對多 (N:N)

今天這部分章節,會優先介紹 1 對 1。
我們用實際的例子來進行說明會更加清楚。

1:1 一對一

假如我們今天想要開一間飲料店
我們會有一個店長 Owner
一個店長會有一間店 Store

假設每個店長可以開一間店,這種關係就是一對一的關係。
=> Owner has one store

可以先從 rails 中產生 Owner 的 Model 並生成對應的資料表來記錄店長的資訊

1
rails g model Owner name phone:integer

再產生 Store 的 Model 並生成對應的資料表來記錄商店的資訊,由於需要多一個 owner_id 所以透過指令 owner:references 或是 owner:belongs_to 來產生,這一個欄位可以讓我們知道

1
2
rails g model Store name tel address owner:references
rails g model Store name tel address owner:belongs_to (同上一行)


兩者的關係可以看到上圖表示,在 onwer 的 model 裡面可以加上對應的關聯,如果需要讓兩者之間有所關聯,belongs to 的那方就要有對應的 id 去紀錄,這邊就是透過 owner_id 。

has one 建立及產生的方法

到 Owner model 建立 has_one 關聯

1
2
3
class Owner < ApplicationRecord
has_one :store
end

關聯產生後就自動產生以下方法,你可以用來在 controller 傳遞資料時進行關聯的查找,或是 console 中操作資料時使用。

store
store=
build_store
create_store

其中 build 和 create 差異,build 還沒存入資料庫,create 直接存入

用 console 建立一個 Owner 然後用 crate_store 建立一個 Store

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Owner.create(name:"Sean", phone:"0912345678")

o1 = Owner.first

o1.create_store(name:"五石蘭", tel:"031234567", address:"新竹縣")

Store.last
id: 1,
name: "五石蘭",
tel: "031234567",
address: "新竹縣",
owner_id: 1,
created_at: Fri, 07 Oct 2022 07:22:23.353390000 UTC +00:00,
updated_at: Fri, 07 Oct 2022 07:22:23.353390000 UTC +00:00>

belongs_to 建立及產生的方法

在 store 的 model 裡面也看到已經加好的關聯 (owner:references/owner:belongs_to 自動產生),如果沒有透過之前指令也可以自己加上去,或是你沒有要用到產生的方法也可以不寫。

1
2
3
class Store < ApplicationRecord
belongs_to :owner
end

加上後也會因關聯產生後就自動產生以下方法

owner
owner=

用上面建立好的 store 可以反向利用 owner 查到擁有者是誰,你也可以用 onwer= 來更改擁有者的資料

1
2
3
4
5
6
7
8
9
10
11
s1 = Store.last

s1.owner
Owner Load (0.5ms) SELECT "owners".* FROM "owners" WHERE "owners"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=>
#<Owner:0x00007f8e292a7308
id: 1,
name: "Sean",
phone: "0912345678",
created_at: Fri, 07 Oct 2022 07:18:45.627220000 UTC +00:00,
updated_at: Fri, 07 Oct 2022 07:18:45.627220000 UTC +00:00>

補充:

  1. has_one 跟 belongs_to 方法需要同時設定嗎?
    不一定。如果不需要「從 Store 反查 Owner」的方法,那 belongs_to 就不需要設定了。或是不需要從 Owner 創建 store 或是查詢,也可以不用寫 has_one。

  2. 如果只設定 has_one 或 belongs_to 其中一項的話會怎樣?
    有設定的話就會有方法,沒設定也沒關係,依造自己需要進行設定。


參考資料:

  1. 為你自己學 Ruby on Rails