哈囉,大家好!
那麼我們今天開始為Model 和Database 加上關聯吧!
不知魯魯們是不是跟被翻爛的書一樣,每次聽到關聯就像斷片,除卻為什麼要加這件事情不談,本篇就先來單就該怎麼加討論吧!
你可能聽過:
:只加上 has_one、has_many、belongs_to 等還沒做完關聯?
:在資料表要加上PK、FK?
:那加了PK、FK 就算加上關聯了嗎?
:那到底怎麼樣才叫加了關聯、加了關聯與否又會有什麼差別呢?
首先,我們先看到Rails Guide - Active Record Association 篇:
1 Why Associations?
In Rails, an association is a connection between two Active Record models. Why do we need associations between models? Because they make common operations simpler and easier in your code.
在討論simpler and eaiser 是怎麼做到的前,我們不妨先來畫關聯圖,以便解釋後面的情境吧!
(以上為利用drawio 畫的,是流程圖、ER 圖的繪製利器)
釐清了自己資料表的關聯性後,我們就來試試以上幾個情境吧!
情境1:如果沒加上has_many、belongs_to,以Podcast、Episode 為例:
# 尚未加上has_many、belongs_to
irb(main):001:0> Podcast.last.episodes
Podcast Load (0.5ms) SELECT "podcasts".* FROM "podcasts" ORDER BY "podcasts"."id" DESC LIMIT $1 [["LIMIT", 1]]
Traceback (most recent call last):
1: from (irb):4
NoMethodError (undefined method `episodes' for #<Podcast:0x00007fba05cea718>)
# 加上Podcast has_many :episodes
irb(main):002:0> Podcast.last.episodes
Podcast Load (0.3ms) SELECT "podcasts".* FROM "podcasts" ORDER BY "podcasts"."id" DESC LIMIT $1 [["LIMIT", 1]]
Traceback (most recent call last):
ActiveRecord::StatementInvalid (PG::UndefinedColumn: ERROR: column episodes.podcast_id does not exist)
LINE 1: SELECT "episodes".* FROM "episodes" WHERE "episodes"."podcas..."
# 同理,沒加上Episode belongs_to :podcast
irb(main):003:0> Episode.last.podcast
Episode Load (0.2ms) SELECT "episodes".* FROM "episodes" ORDER BY "episodes"."id" DESC LIMIT $1 [["LIMIT", 1]]
Traceback (most recent call last):
1: from (irb):25
NoMethodError (undefined method `podcast' for #<Episode:0x00007fb9ff9f6080>)
看到這邊,大概能知道has_many 和belongs_to 能為Model 增加association 的若干方法,那讓我們偷偷來看看究竟增加了哪些方法 XD:
irb(main):004:0> Episode.instance_methods.count
329
# 加上belongs_to :podcast 後
irb(main):005:0> Episode.instance_methods.count
336
大家也有興奮的感覺了嗎?我們來驗證看看多了哪些方法:
# 未加上belongs_to :podcast 前
methods_before = []
methods_before << Episode.instance_methods
# 加上belongs_to :podcast 後
reload!
methods_after = []
methods_after << Episode.instance_methods
# 有沒有興奮的感覺!XD
irb(main):022:0> methods_after.flatten - methods_before.flatten
[
[0] "autosave_associated_records_for_podcast",
[1] "build_podcast",
[2] "create_podcast",
[3] "create_podcast!",
[4] "podcast",
[5] "podcast=",
[6] "reload_podcast"
]
我們可看到加上belongs_to 的方法後,會給予其上面的方法;而若加上has_on、has_many,也會給予其相對應的關聯方法,至於方法是什麼呢,我們就之後再補充說明啦!
補充:
has_one 給的方法
has_many 給的方法
has_and_belongs_to_many 給的方法
belongs_to 給的方法
來偷偷對一下上面的跟Rails Guide 列的方法:
# When you declare a belongs_to association, the declaring class automatically gains 8 methods related to the association:
association # ✔️
association=(associate) # ✔️
build_association(attributes = {}) # ✔️
create_association(attributes = {}) # ✔️
create_association!(attributes = {}) # ✔️
reload_association # ✔️
association_changed?
association_previously_changed?
# 所以就知道可以研究什麼了嗎?XD
...
那麼今天的文章就到這到一段落啦,謝謝大家~