昨天講述了一些 Active Record Model 的概念之後,今天來點 Active Record Associations 關聯性!
在 Rails 中,Active Record 關聯是指不同 Model 之間的連結與關係。
我們在一個專案裡,一定不只有一個 Model,會同時存在許多 Model,
在 Rails 裡,我們可以透過關聯將這些 Model 連結在一起,大致上歸納出以下優點:
Model 需要關聯性是為了更好地組織和管理資料,以及實現資料間的關聯和連結。
資料的結構化:通常一個應用程式涉及多個資料,彼此之間可能存在著很複雜的關係。
可以將這些資料的關係結構化,使得資料庫中的資料更容易理解和管理。
整合資料:資料往往存在著相互關聯的情況。例如:一個使用者有多個訂單。
可以將這些相關聯的資料整合在一起,使得查詢和操作資料更加方便。
簡化資料存取:在查詢資料時不需要手動撰寫複雜的 SQL 語句,而是使用 Rails 提供的簡單方法即可。這樣可以節省開發時間,並減少出錯的可能性。
維護性和擴展性:當應用程式需要新增新的資料實體或調整資料結構時,使用 Model 的關聯性可以輕鬆地進行修改而不影響其他部分的程式碼。
這種關聯性可以在資料庫層面建立表格之間的連結,使得資料之間可以相互關聯和互動,
進而簡化資料的查詢和操作。
Rails 支援以下六種關聯:
透過關聯而產生的方法,你可以在 Model 類別中指定關聯的類別和條件,Rails 將根據這些定義在資料庫層面建立對應的關聯。
belongs_to
生成 Profile Model 的指令:rails generate model Profile bio:text user:belongs_to
(or)rails generate model Profile bio:text user:references
--> 這樣就會在 Profile 資料表中生成 user_id
這個 foreign key
# Profile 模型
class Profile < ApplicationRecord
belongs_to :user
end
has_one
生成 User Model 的指令:rails generate model User name:string
# User 模型
class User < ApplicationRecord
has_one :profile
end
當有 has_one :profile
時,這個關聯會生成以下方法:
profile -> user.profile # 找出用戶的個人檔案
profile= -> user.profile = profile # 將一個現有的個人檔案分配給用戶,以更改用戶的個人檔案。
build_profile -> user.build_profile(bio: 'About me') # 建立一個新個人檔案,但該個人檔案不會立即保存到資料庫中。
create_profile -> user.create_profile(bio: 'About me') # 建立一個新個人檔案,同時個人檔案會保存到資料庫中。
create_profile! -> user.create_profile!(bio: 'About me') # 當保存個人檔案時,如果存在驗證失敗或其他錯誤,將引發異常(exception),而非返回 false。
reload_profile -> user.reload_profile # 如果你修改了個人檔案,但希望獲取最新的數據,可以使用 reload_profile 方法。
has_one :through(透過一對一關聯):
生成 User Model 的指令:rails generate model User name:string
生成 Profile Model 的指令:rails generate model Profile bio:text
生成 Account Model 的指令:rails generate model Account user:references
–> 這樣就會在 Account 資料表中生成 user_id
這個 foreign key
# User 模型
class User < ApplicationRecord
has_one :account
has_one :profile, through: :account
end
# Account 模型
class Account < ApplicationRecord
belongs_to :user
has_one :profile
end
# Profile 模型
class Profile < ApplicationRecord
belongs_to :account
end
# 建立使用者
user = User.create(name: 'Viii')
# 建立帳戶,並與使用者建立關聯
account = user.create_account
# 建立個人檔案,並與帳戶建立關聯
profile = account.build_profile(bio: 'About me')
# 保存關聯記錄到資料庫
user.save
# 查找使用者的帳戶
account = user.account
# 查找使用者的個人檔案(透過帳戶關聯)
profile = user.profile
# 查找帳戶所屬的使用者
account_user = account.user
# 查找帳戶關聯的個人檔案
account_profile = account.profile
has_many
# User 模型
class User < ApplicationRecord
has_many :articles
end
# Article 模型
class Article < ApplicationRecord
belongs_to :user
end
當有 has_many :articles
時,這個關聯會自帶以下方法:
articles -> user.articles # 獲取該用戶的所有文章
articles<<(object, ...) -> user.articles << article1 # 來將一篇文章添加到用戶的文章集合中
articles.delete(object, ...) -> user.articles.delete(article1) # 來刪除用戶的某篇文章
articles.destroy(object, ...) -> user.articles.destroy(article1) # 來刪除用戶的某篇文章,同時也會刪除該文章的資料庫記錄
articles=(objects) -> user.articles = [article1, article2] # 來設定用戶的所有文章
article_ids -> user.article_ids # 來獲取用戶的所有文章的 ID
article_ids=(ids) -> user.article_ids = [1, 2, 3] # 來設定用戶的所有文章的 ID
articles.clear -> articles.clear # 用於從關聯集合中刪除所有 Article 物件,但不會銷毀這些對象。
articles.empty? -> articles.empty? # 用於檢查關聯集合是否為空,如果集合中不包含任何 Article 物件,則返回 true。
articles.size -> articles.size # 用於獲取關聯集合中的 Article 物件數量。
articles.find(...) -> articles.find # 用於查找關聯集合中滿足指定條件的 Article,使用 id 來查找文章。
articles.where(...) -> articles.where # 用於使用條件查找關聯集合中的 Article,並返回一個 ActiveRecord 查詢。
articles.exists?(...) -> articles.exists? # 用於檢查關聯集合中是否存在滿足指定條件的 Article,如果存在則返回 true,否則返回 false。
articles.build(attributes = {}, ...) -> articles.build # 用於建立一個新的 Article,但不會將其保存到資料庫中。可以選擇性地提供屬性(attributes)作為參數,以自定義新建對象的屬性。
articles.create(attributes = {}) -> articles.create # 用於建立一個新的 Article 並將其保存到資料庫中。可以選擇性地提供屬性(attributes)作為參數,以自定義新建對象的屬性。
articles.create!(attributes = {}) -> articles.create! 方法與 articles.create 方法相似,但當保存文章時,如果存在驗
articles.reload -> articles.reload # 用於重新向數據庫發出查詢,以確保關聯集合的數據是最新的。
在 Rails 中,有兩種方式可以實現多對多關聯:
has_many :through 和 has_and_belongs_to_many。
has_many :through
通常在以下情況下使用:
has_many :through
是更好的選擇。has_many :through
允許你使用 Active Record 查詢方法對中間模型進行操作,進而實現更高級的查詢。has_many :through
更靈活。使用 has_many :through
:
# User 模型
class User < ApplicationRecord
has_many :user_roles
has_many :roles, through: :user_roles
end
# Role 模型
class Role < ApplicationRecord
has_many :user_roles
has_many :users, through: :user_roles
end
# UserRole 模型作為中間模型
class UserRole < ApplicationRecord
belongs_to :user
belongs_to :role
end
has_and_belongs_to_many
has_and_belongs_to_many
關聯是一種簡單的多對多關聯,
不使用中間模型,只需一個連接表(join table)來維護關聯,通常在以下情況下使用:
has_and_belongs_to_many
可以更容易地設置和使用。has_and_belongs_to_many
可能是更簡單的選擇。使用 has_and_belongs_to_many
:
# User 模型
class User < ApplicationRecord
has_and_belongs_to_many :roles
end
# Role 模型
class Role < ApplicationRecord
has_and_belongs_to_many :users
end
簡單來說,如果需要將關聯模型視為獨立的實體來操作,
那麼應該設置一個has_many :through
關聯。
如果不需要對關聯模型進行任何操作,
也許設置一個has_and_belongs_to_many
關聯會更簡單(需要記住在資料庫中創建連接表 join table)。
如果你需要在關聯模型上進行驗證、回調或使用額外的屬性,應該使用has_many :through
。
我們今天先到這!下篇繼續提及 Active Record Associations 的相關概念!
參考資料:
文章同步於個人部落格:Viiisit!(歡迎參觀 ୧ʕ•̀ᴥ•́ʔ୨)