The Types of Associations
在 Rails 中,可以通過 ActiveRecord 來定義不同型別的關聯關系(Associations),包括以下幾種:
-
belongs_to:表示該模型
belongs_to另一個模型,即該模型擁有一個外鍵(foreign key)指向另一個模型的主鍵(primary key),通常用于表示一對一或多對一的關系, -
has_one:表示該模型
has_one另一個模型,即另一個模型擁有一個外鍵指向該模型的主鍵,通常用于表示一對一的關系, -
has_many:表示該模型
has_many另一個模型,即另一個模型擁有一個外鍵指向該模型的主鍵,通常用于表示一對多的關系, -
has_many :through:表示通過中間模型建立多對多的關系,通常用于表示多對多的關系,
-
has_one :through:表示通過中間模型建立一對一或多對一的關系,
-
has_and_belongs_to_many:表示建立一個簡單的多對多的關系,通常用于表示只有兩個模型之間的多對多關系,
需要注意的是,這些關聯關系需要在模型之間正確定義和設定,才能夠正確地在應用程式中使用,并且需要考慮到關聯關系的型別、方向、外鍵、中間模型等因素,正確地定義和使用關聯關系,可以方便地查詢和操作相關資料,并且可以避免出現不必要的代碼和邏輯,
belongs_to
class CreateBooks < ActiveRecord::Migration[7.0]
def change
create_table :authors do |t|
t.string :name
t.timestamps
end
create_table :books do |t|
t.belongs_to :author
t.datetime :published_at
t.timestamps
end
end
end
這是一個創建 authors 和 books 兩個資料庫表的遷移檔案,authors 表包含一個 name 欄位和 created_at 和 updated_at 兩個時間戳欄位,books 表包含一個 author_id 外鍵欄位來關聯 authors 表,一個 published_at 欄位和 created_at 和 updated_at 兩個時間戳欄位,
在 Rails 中,遷移檔案用于創建、修改和洗掉資料庫表和欄位,這個遷移檔案中的 change 方法定義了如何創建 authors 和 books 兩個表,在 create_table 塊中,我們可以宣告表中的欄位和型別,以及其他選項,如外鍵關聯等,在這個例子中,我們使用 belongs_to 方法來宣告 books 表與 authors 表之間的關聯關系,
當我們運行這個遷移檔案時,Rails 將會執行 change 方法中的代碼,并在資料庫中創建 authors 和 books 兩個表,同時,Rails 還會自動創建 author_id 外鍵索引,以確保 books 表中的每個行都關聯到 authors 表中的一個行,
belongs_to不能確保參考一致性,因此根據用例,您可能還需要在參考列上添加資料庫級外鍵約束,如下所示:
create_table :books do |t|
t.belongs_to :author, foreign_key: true
# ...
end
has_one
當使用 has_one 方法時,一個模型將擁有另一個模型的一個實體作為其屬性之一,這通常用于表示一對一關系,其中一個模型記錄與另一個模型的關聯,而另一個模型只有一個與之相關的記錄,
以下是一個使用 has_one 方法的例子,假設有一個 User 模型和一個 Profile 模型,每個用戶只有一個個人資料:
class User < ApplicationRecord
has_one :profile
end
class Profile < ApplicationRecord
belongs_to :user
end
在上面的代碼中,User 模型使用 has_one 方法宣告了與 Profile 模型之間的關聯關系,而 Profile 模型使用 belongs_to 方法宣告了與 User 模型之間的關聯關系,
在這個例子中,User 模型將獲得一個名為 profile 的屬性,可以使用它來訪問與用戶相關聯的個人資料,例如,可以使用 user.profile 來獲取用戶的個人資料,在 Profile 模型中,user 屬性將被用于訪問與個人資料相關聯的用戶,
值得注意的是,在 has_one 方法中,默認情況下,Rails 將使用 user_id 欄位作為外鍵來關聯兩個模型,因此在 Profile 模型中需要使用 belongs_to 方法來宣告與 User 模型之間的關聯關系,
has_one :through
has_one :through 是 Rails 中用于宣告一對一關系的方法,它用于表示兩個模型之間通過第三個關聯模型建立的關系,這個方法通常用于表示一個模型與另一個模型之間的一對一關系,其中一個模型可以關聯一個與之關聯的記錄,而每個關聯記錄只能關聯一個與之關聯的記錄,
以下是一個使用 has_one :through 方法的例子,假設有一個 User 模型和一個 Profile 模型,它們之間通過 ProfileLink 模型建立關聯,每個用戶只能擁有一個個人資料:
class User < ApplicationRecord
has_one :profile_link
has_one :profile, through: :profile_link
end
class Profile < ApplicationRecord
has_one :profile_link
has_one :user, through: :profile_link
end
class ProfileLink < ApplicationRecord
belongs_to :user
belongs_to :profile
end
在上面的代碼中,User 模型和 Profile 模型都使用 has_one :through 方法宣告了與 ProfileLink 模型之間的關聯關系,而 ProfileLink 模型使用 belongs_to 方法宣告了與 User 模型和 Profile 模型之間的關聯關系,
在這個例子中,User 模型將獲得一個名為 profile 的屬性,可以使用它來訪問與用戶相關聯的個人資料,例如,可以使用 user.profile 來獲取與用戶相關聯的個人資料,在 Profile 模型中,user 屬性將被用于訪問與個人資料相關聯的用戶,
值得注意的是,在 has_one :through 方法中,需要指定通過哪個關聯模型建立一對一關系,例如:has_one :profile, through: :profile_link 表示 User 模型通過 ProfileLink 模型與 Profile 模型建立了一對一關系,
同時,在這個例子中,ProfileLink 模型還可以添加其他屬性,例如 status 表示用戶的個人資料狀態等,以便更好地描述關聯關系,
has_many
has_many 是 Rails 中用于宣告一對多關系的方法,它用于表示一個模型物件擁有多個其他模型物件的集合,這個方法通常用于表示一個模型與另一個模型之間的關聯,其中一個模型可以擁有多個與之關聯的記錄,
以下是一個使用 has_many 方法的例子,假設有一個 User 模型和一個 Post 模型,每個用戶可以擁有多篇文章:
class User < ApplicationRecord
has_many :posts
end
class Post < ApplicationRecord
belongs_to :user
end
在上面的代碼中,User 模型使用 has_many 方法宣告了與 Post 模型之間的關聯關系,而 Post 模型使用 belongs_to 方法宣告了與 User 模型之間的關聯關系,
在這個例子中,User 模型將獲得一個名為 posts 的屬性,可以使用它來訪問與用戶相關聯的所有文章,例如,可以使用 user.posts 來獲取與用戶相關聯的所有文章,在 Post 模型中,user 屬性將被用于訪問與文章相關聯的用戶,
值得注意的是,在 has_many 方法中,默認情況下,Rails 將使用 user_id 欄位作為外鍵來關聯兩個模型,因此在 Post 模型中需要使用 belongs_to 方法來宣告與 User 模型之間的關聯關系,
has_many :through
has_many :through 是 Rails 中用于宣告多對多關系的方法,它用于表示兩個模型之間通過第三個關聯模型建立的關系,這個方法通常用于表示一個模型與另一個模型之間的多對多關系,其中一個模型可以關聯多個與之關聯的記錄,而每個關聯記錄都可以關聯多個與之關聯的記錄,
以下是一個使用 has_many :through 方法的例子,假設有一個 User 模型和一個 Group 模型,它們之間通過 Membership 模型建立關聯,每個用戶可以屬于多個組:
class User < ApplicationRecord
has_many :memberships
has_many :groups, through: :memberships
end
class Group < ApplicationRecord
has_many :memberships
has_many :users, through: :memberships
end
class Membership < ApplicationRecord
belongs_to :user
belongs_to :group
end
在上面的代碼中,User 模型和 Group 模型都使用 has_many :through 方法宣告了與 Membership 模型之間的關聯關系,而 Membership 模型使用 belongs_to 方法宣告了與 User 模型和 Group 模型之間的關聯關系,
在這個例子中,User 模型將獲得一個名為 groups 的屬性,可以使用它來訪問與用戶相關聯的所有組,例如,可以使用 user.groups 來獲取與用戶相關聯的所有組,在 Group 模型中,users 屬性將被用于訪問所有屬于該組的用戶,
值得注意的是,在 has_many :through 方法中,需要指定通過哪個關聯模型建立多對多關系,例如:has_many :groups, through: :memberships 表示 User 模型通過 Membership 模型與 Group 模型建立了多對多關系,
同時,在這個例子中,Membership 模型還可以添加其他屬性,例如 status 表示用戶在組中的狀態等,以便更好地描述關聯關系,
has_many 和 has_many :through 都是 Rails 中用于建立關聯關系的方法,但它們之間有一些區別,
has_many :through和has_many 區別
has_many 建立的是一對多的關聯關系,其中一個模型物件擁有多個其他模型物件的集合,這個方法通常用于表示一個模型與另一個模型之間的關聯,其中一個模型可以擁有多個與之關聯的記錄,例如,一個用戶可以擁有多篇文章,
has_many :through 建立的是多對多的關聯關系,其中兩個模型之間通過第三個關聯模型建立的關系,這個方法通常用于表示一個模型與另一個模型之間的多對多關系,其中一個模型可以關聯多個與之關聯的記錄,而每個關聯記錄都可以關聯多個與之關聯的記錄,例如,一個用戶可以屬于多個組,一個組也可以有多個用戶,
因此,has_many :through 更加靈活,可以用于建立更為復雜的關聯關系,同時,has_many :through 還可以在關聯模型中添加其他屬性,例如關聯記錄的狀態等,
需要注意的是,在使用 has_many :through 方法建立多對多關聯關系時,需要指定通過哪個關聯模型建立多對多關系,而在使用 has_many 建立一對多關聯關系時,則不需要指定,
The has_and_belongs_to_many Association
has_and_belongs_to_many 是 Rails 中用于宣告多對多關系的另一種方法,與 has_many :through 不同的是,它不需要使用第三個關聯模型來建立多對多關系,這個方法通常用于表示兩個模型之間的多對多關系,其中一個模型可以關聯多個與之關聯的記錄,而每個關聯記錄也可以關聯多個與之關聯的記錄,
以下是一個使用 has_and_belongs_to_many 方法的例子,假設有一個 Book 模型和一個 Author 模型,它們之間建立了多對多關系:
class Book < ApplicationRecord
has_and_belongs_to_many :authors
end
class Author < ApplicationRecord
has_and_belongs_to_many :books
end
在上面的代碼中,Book 模型和 Author 模型都使用 has_and_belongs_to_many 方法宣告了彼此之間的多對多關系,
在這個例子中,Book 模型將獲得一個名為 authors 的屬性,可以使用它來訪問與圖書相關聯的所有作者,例如,可以使用 book.authors 來獲取與書籍相關聯的作者串列,在 Author 模型中,books 屬性將被用于訪問與作者相關聯的所有書籍,
需要注意的是,在使用 has_and_belongs_to_many 方法建立多對多關聯關系時,需要在資料庫中創建一個中間表來存盤關聯關系,這個中間表的名稱應該是兩個模型名稱的復數形式的字母排序后的連接,例如,在上面的例子中,中間表的名稱應該是 authors_books,
同時,使用 has_and_belongs_to_many 方法建立多對多關聯關系時,不能在中間表中添加其他屬性,因為它只是用于存盤兩個模型之間的關聯關系,如果需要在關聯關系中添加其他屬性,應該使用 has_many :through 方法來建立多對多關系,
Choosing Between belongs_to and has_one
在 Rails 中,belongs_to 和 has_one 是兩種用于定義兩個模型之間的一對一關系的方法,選擇它們之間的方法取決于兩個模型之間關系的性質,
當外鍵存盤在宣告關聯的模型的表中時,使用 belongs_to,例如,考慮一個 Car 模型,它屬于一個 Manufacturer:
class Car < ApplicationRecord
belongs_to :manufacturer
end
class Manufacturer < ApplicationRecord
has_many :cars
end
在這個例子中,cars 表有一個外鍵 manufacturer_id 參考 manufacturers 表,由于外鍵存盤在 cars 表中,我們在 Car 模型中使用 belongs_to 來定義關聯,
另一方面,當外鍵存盤在關聯模型的表中時,使用 has_one,例如,考慮一個 Person 模型,它有一個 Address:
class Person < ApplicationRecord
has_one :address
end
class Address < ApplicationRecord
belongs_to :person
end
在這個例子中,addresses 表有一個外鍵 person_id 參考 people 表,由于外鍵存盤在 addresses 表中,我們在 Person 模型中使用 has_one 來定義關聯,
一般來說,選擇 belongs_to 還是 has_one 取決于外鍵存盤的位置,如果它存盤在宣告關聯的模型的表中,使用 belongs_to,如果它存盤在關聯模型的表中,使用 has_one,
Choosing Between has_many :through and has_and_belongs_to_many
在 Rails 中,has_many :through 和 has_and_belongs_to_many 是兩種用于定義多對多關系的方法,選擇它們之間的方法取決于你是否需要在關聯關系中存盤其他屬性,
has_many :through 允許你使用中間模型來連接兩個模型,并且可以在中間模型中存盤其他屬性,這使得 has_many :through 更加靈活,適用于需要在關聯關系中存盤更多資訊的情況,例如,考慮一個 Patient 模型和一個 Doctor 模型,它們之間需要建立多對多關系,而每個關聯關系還需要存盤一個 appointment_date 屬性:
class Patient < ApplicationRecord
has_many :appointments
has_many :doctors, through: :appointments
end
class Doctor < ApplicationRecord
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ApplicationRecord
belongs_to :patient
belongs_to :doctor
end
在上面的例子中,Patient 模型和 Doctor 模型之間的多對多關系通過 Appointment 模型建立,Appointment 模型中存盤了 appointment_date 屬性,表示預約時間,可以使用以下代碼來訪問與患者相關聯的所有醫生:
patient.doctors
has_and_belongs_to_many 允許你在兩個模型之間建立簡單的多對多關系,但不能在中間表中存盤其他屬性,因此,如果你不需要在關聯關系中存盤其他屬性,可以使用 has_and_belongs_to_many,例如,考慮一個 Student 模型和一個 Course 模型,它們之間需要建立多對多關系:
class Student < ApplicationRecord
has_and_belongs_to_many :courses
end
class Course < ApplicationRecord
has_and_belongs_to_many :students
end
在上面的例子中,Student 模型和 Course 模型之間的多對多關系可以直接通過中間表建立,而不需要使用中間模型,
總之,如果你需要在關聯關系中存盤其他屬性,應該使用 has_many :through,如果不需要存盤其他屬性,則可以使用 has_and_belongs_to_many 來建立多對多關系,
Polymorphic Associations
在 Rails 中,多型關聯(Polymorphic Associations)允許一個模型屬于多個不同型別的其他模型,同時這些其他模型也可以有多個關聯的模型,這種關聯通常用于需要共享相同行為或屬性的模型之間,
例如,考慮一個 Comment 模型,它可以屬于多個其他模型(例如 Post 和 Photo),同時這些其他模型也可以有多個評論:
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
end
class Post < ApplicationRecord
has_many :comments, as: :commentable
end
class Photo < ApplicationRecord
has_many :comments, as: :commentable
end
在上面的例子中,Comment 模型使用 belongs_to 方法宣告了多型關聯,commentable 是一個多型關聯欄位,它可以屬于任何其他模型,在 Post 和 Photo 模型中,使用 has_many 方法宣告了多型關聯關系,并使用 as 選項指定了多型關聯欄位的名稱,
使用多型關聯時,需要在資料庫中創建一個 comments 表,這個表需要包含一個 commentable_type 欄位和一個 commentable_id 欄位,用于存盤關聯的模型,可以使用以下代碼創建 comments 表:
rails generate migration CreateComments commentable:references{polymorphic}:index body:text
上面的代碼將生成一個名為 CreateComments 的遷移檔案,該檔案將創建一個 comments 表,并添加一個 commentable_type 欄位和一個 commentable_id 欄位,同時還添加了一個 body 欄位用于存盤評論內容,
可以使用以下代碼來訪問與 Post 相關聯的所有評論:
post.comments
可以使用以下代碼來訪問與 Photo 相關聯的所有評論:
photo.comments
總之,多型關聯允許一個模型屬于多個不同型別的其他模型,并且這些其他模型也可以有多個關聯的模型,這種關聯通常用于需要共享相同行為或屬性的模型之間,
Self Joins
Self Joins 是指在一個表中,通過外鍵關聯自身的另一行資料,Self Joins 常用于需要建立層次結構的資料模型,例如組織結構、分類等,
在 Rails 中,可以通過在模型中使用 belongs_to 和 has_many 方法來實作 Self Joins,具體實作方式是,在模型中定義一個外鍵欄位來參考自身的 ID,然后通過 belongs_to 方法宣告自身與父級的關聯,再通過 has_many 方法宣告自身與子級的關聯,
下面是一個簡單的例子,假設有一個 Category 模型,每個分類可以有多個子分類,同時也可以屬于一個父分類:
class Category < ApplicationRecord
belongs_to :parent, class_name: 'Category', optional: true
has_many :children, class_name: 'Category', foreign_key: 'parent_id'
end
上面的代碼中,Category 模型通過 belongs_to 方法宣告與父級的關聯,使用 class_name 選項指定關聯的模型名稱為 Category,同時使用 optional: true 選項表示父級可以為空,通過 has_many 方法宣告與子級的關聯,使用 class_name 選項指定關聯的模型名稱為 Category,使用 foreign_key 選項指定外鍵欄位為 parent_id,
在資料庫中,需要創建一個 categories 表來存盤分類,該表需要包含一個 parent_id 欄位用于存盤父級分類的 ID,可以使用以下代碼創建 categories 表:
rails generate migration CreateCategories name:string parent:references
上面的代碼將生成一個名為 CreateCategories 的遷移檔案,該檔案將創建一個 categories 表,并添加一個 name 欄位用于存盤分類名稱,以及一個 parent_id 欄位用于存盤父級分類的ID,
可以使用以下代碼來訪問一個分類的父級:
category.parent
可以使用以下代碼來訪問一個分類的子級:
category.children
總之,Self Joins 允許在一個表中通過外鍵關聯自身的另一行資料,常用于需要建立層次結構的資料模型,在 Rails 中,可以通過在模型中使用 belongs_to 和 has_many 方法來實作 Self Joins,通過定義一個外鍵欄位來參考自身的 ID,然后宣告自身與父級的關聯和自身與子級的關聯,
Tips, Tricks, and Warnings
Controlling Caching
# retrieves books from the database
author.books.load
# uses the cached copy of books
author.books.size
# uses the cached copy of books
author.books.empty?
這是關于 ActiveRecord 的代碼示例,它展示了如何使用快取來訪問一個作者(author)的書籍(books),
第一行代碼 author.books.load 從資料庫中檢索作者的書籍,并將其存盤在快取中,這意味著在下一行代碼和之后的代碼中,將使用快取中的書籍,而不是從資料庫中再次檢索它們,
第二行代碼 author.books.size 回傳快取中作者的書籍數量,而不是從資料庫中再次檢索它們,這是因為在第一行代碼中,author.books.load 將書籍存盤在快取中,因此在下一行代碼中,可以直接從快取中獲取書籍數量,而不需要從資料庫中再次檢索它們,
第三行代碼 author.books.empty? 回傳一個布林值,指示快取中作者的書籍是否為空,同樣地,這是因為在第一行代碼中,author.books.load 將書籍存盤在快取中,因此在第三行代碼中,可以直接從快取中檢查書籍是否為空,而不需要從資料庫中再次檢索它們,
這種使用快取的方式可以幫助提高應用程式的性能,因為它避免了在每次訪問物件時都需要從資料庫中檢索資料的開銷,但是,需要注意的是,如果在快取中的資料與資料庫中的資料不同步,則可能會導致資料不一致,因此,在使用快取時,需要仔細考慮如何更新快取以確保資料的正確性,
Creating Foreign Keys for belongs_to Associations
在關系型資料庫中,外鍵(Foreign Key)是一種用于建立表之間關聯的技術,當一個表中的列參考另一個表的主鍵時,就會創建一個外鍵,在 Rails 中,通過使用 belongs_to 關聯,可以輕松地創建外鍵,以下是一個實際的示例:
假設您正在構建一個博客應用程式,其中包含多個文章(Post)和多個評論(Comment),每個評論都屬于一個特定的文章,因此您需要在評論表中創建一個外鍵,以參考文章表中的主鍵,
首先,您需要在 Comment 模型中添加一個 belongs_to 關聯:
class Comment < ApplicationRecord
belongs_to :post
end
然后,您需要在評論表中添加一個名為 post_id 的整數列,用于存盤文章的主鍵值,在 Rails 中,可以使用資料庫遷移來添加此列:
rails generate migration AddPostIdToComments post:references
這將生成一個包含 add_reference 方法的遷移檔案,該方法將在評論表中添加一個 post_id 列,并將其設定為參考文章表的主鍵,
最后,您需要運行遷移,以將更改應用于資料庫:
rake db:migrate
現在,當您創建一個新評論時,Rails 將自動在評論表中設定正確的 post_id 值,以參考相應的文章,
例如,您可以通過以下代碼將一條評論關聯到一篇文章:
post = Post.first
post.comments.create(body: "Great post!")
這是一個示例代碼,用于在 Rails 應用程式中創建新評論并將其與特定文章關聯,
首先,Post.first 獲取文章表中的第一篇文章,并將其分配給變數 post,然后,post.comments.create 用于創建一個新評論,并將其與 post 變數中存盤的文章關聯起來,這是通過 has_many :comments 關聯和 Comment 模型中的 belongs_to :post 關聯實作的,
具體來說,post.comments 回傳一個關聯物件,該物件允許您訪問與特定文章相關聯的所有評論,然后,create 方法用于創建一個新評論,并將其與 post 關聯起來,在本例中,新評論的 body 屬性設定為 "Great post!",
最后,新評論將被保存到資料庫中,并且在 comments 表中將包含一個新行,其中包含評論的內容和與之相關聯的文章的主鍵值,
這是一個典型的 Rails 應用程式中的代碼示例,用于演示如何使用關聯模型和創建新物件,
Creating Join Tables for has_and_belongs_to_many Associations
在 Rails 中,has_and_belongs_to_many(HABTM)關聯用于建立多對多的關系,在關系型資料庫中,通常需要使用一個中間表來存盤這種關聯,這個中間表被稱為“聯接表”(Join Table),
創建聯接表的步驟如下:
-
創建一個名為
table1_table2的表,其中table1和table2分別是要關聯的兩個表的名稱,例如,如果您想要關聯users和groups表,則可以創建一個名為users_groups的聯接表, -
添加兩個整數列,分別用于存盤關聯表的主鍵,這些列通常被命名為
table1_id和table2_id,例如user_id和group_id, -
向
table1和table2中的模型檔案中添加has_and_belongs_to_many關聯,例如,在User模型中,您可以這樣添加一個has_and_belongs_to_many關聯:
class User < ApplicationRecord
has_and_belongs_to_many :groups
end
這將指示 Rails 通過 users_groups 表將 users 和 groups 表關聯起來,
以下是一個實際的示例:
假設您正在構建一個社交網路應用程式,其中用戶(User)可以加入多個組(Group),而每個組也可以有多個用戶,為了實作這種多對多關系,您需要創建一個聯接表,
首先,您可以使用以下命令創建一個名為 groups_users 的聯接表:
rails generate migration CreateGroupsUsers
然后,您可以使用以下代碼向遷移檔案中添加表的定義:
class CreateGroupsUsers < ActiveRecord::Migration[6.1]
def change
create_table :groups_users, id: false do |t|
t.references :group, null: false, foreign_key: true
t.references :user, null: false, foreign_key: true
end
end
end
這將創建一個名為 groups_users 的聯接表,并添加 group_id 和 user_id 兩個整數列,用于存盤關聯表的主鍵,
最后,您可以向 User 和 Group 模型中添加 has_and_belongs_to_many 關聯,以指示它們之間的多對多關系:
class User < ApplicationRecord
has_and_belongs_to_many :groups
end
class Group < ApplicationRecord
has_and_belongs_to_many :users
end
現在,您可以使用 << 運算子向用戶添加組,例如:
user = User.first
group = Group.first
user.groups << group
這將將 user 和 group 關聯起來,并在 groups_users 表中添加一個新行,其中包含 user_id 和 group_id 的值,
通過使用 has_and_belongs_to_many 關聯和聯接表,您可以輕松地建立多對多關系,并在 Rails 應用程式中保存和檢索相關資料,
Controlling Association Scope
在 Rails 中,可以使用 scope 方法來控制關聯模型的查詢范圍,這可以幫助您過濾不必要的資料,以提高應用程式的性能和可維護性,
例如,假設您正在構建一個電子商務應用程式,其中訂單(Order)有多個訂單項(OrderItem),并且每個訂單項都屬于一個特定的產品(Product),現在,您想要檢索某個產品的所有訂單項,
首先,您可以在 Product 模型中添加一個 has_many 關聯,以指示每個產品都有多個訂單項:
class Product < ApplicationRecord
has_many :order_items
end
然后,您可以使用 scope 方法來指定只檢索與特定產品相關聯的訂單項:
class OrderItem < ApplicationRecord
belongs_to :product
scope :for_product, -> (product) { where(product_id: product.id) }
end
這將創建一個名為 for_product 的作用域,它接受一個產品物件作為引數,并回傳與該產品相關聯的所有訂單項,
現在,您可以在控制器或視圖中使用 for_product 作用域來檢索與特定產品相關聯的所有訂單項,例如,假設您正在顯示某個產品的詳細資訊,并想要列出所有相關的訂單項:
def show
@product = Product.find(params[:id])
@order_items = OrderItem.for_product(@product)
end
這將檢索與 @product 相關聯的所有訂單項,并將它們分配給 @order_items 變數,由于使用了作用域,查詢將僅回傳與特定產品相關聯的訂單項,而不是所有訂單項,從而提高了查詢的性能和可維護性,
通過使用作用域方法,您可以輕松地控制關聯模型的查詢范圍,并過濾不必要的資料,以提高應用程式的性能和可維護性,
Bi-directional Associations
在 Rails 中,雙向關聯(Bi-directional Associations)是指兩個關聯模型之間的相互關系,其中每個模型都可以訪問另一個模型,這可以通過在兩個模型中都定義關聯來實作,
例如,假設您正在構建一個博客應用程式,其中文章(Post)可以有多個標簽(Tag),而每個標簽也可以與多篇文章相關聯,為了實作這種雙向關聯,您可以在 Post 和 Tag 模型中都定義一個關聯,
首先,您可以在 Post 模型中添加一個 has_and_belongs_to_many 關聯,以指示每篇文章都可以有多個標簽:
class Post < ApplicationRecord
has_and_belongs_to_many :tags
end
然后,您可以在 Tag 模型中添加一個相反的 has_and_belongs_to_many 關聯,以指示每個標簽也可以與多篇文章相關聯:
class Tag < ApplicationRecord
has_and_belongs_to_many :posts
end
現在,您可以在控制器或視圖中使用這些關聯來訪問相互關聯的模型,例如,假設您想要列出所有帶有特定標簽的文章:
def index
@tag = Tag.find(params[:tag_id])
@posts = @tag.posts
end
這將檢索與 @tag 相關聯的所有文章,并將它們分配給 @posts 變數,由于使用了雙向關聯,您可以通過 @tag.posts 訪問所有相關的文章,也可以通過 @post.tags 訪問所有相關的標簽,
雙向關聯使得在兩個關聯模型之間進行導航變得非常容易,通過在每個模型中都定義關聯,您可以輕松地訪問相互關聯的資料,并簡化代碼的撰寫和維護,
Detailed Association Reference
belongs_to Association Reference
這些方法都是 ActiveRecord 中用于操作關聯關系的方法,主要用于設定、創建、檢索和重新加載關聯物件,下面是這些方法的解釋:
-
association:獲取關聯物件,例如,如果Book模型與Author模型存在belongs_to關聯關系,則可以使用book.author獲取與該書籍關聯的作者物件, -
association=(associate):設定關聯物件,例如,如果Book模型與Author模型存在belongs_to關聯關系,則可以使用book.author = author將book物件與特定的author物件關聯起來, -
build_association(attributes = {}):創建一個新的關聯物件,并將其與當前物件關聯起來,例如,如果Book模型與Author模型存在has_one關聯關系,則可以使用book.build_author(author_name: "John Doe")創建一個新的Author物件,并將其與book物件關聯起來, -
create_association(attributes = {}):創建一個新的關聯物件,并將其與當前物件關聯起來,然后將其保存到資料庫中,例如,如果Book模型與Author模型存在has_many關聯關系,則可以使用book.authors.create(author_name: "John Doe")創建一個新的Author物件,并將其與book物件關聯起來,然后將其保存到資料庫中, -
create_association!(attributes = {}):與create_association方法類似,但是如果創建失敗(例如,因為驗證失敗),則會引發例外, -
reload_association:重新加載關聯物件,并將其與資料庫中的最新資料同步,例如,如果您對關聯物件進行了更改,并希望檢索最新版本,則可以使用book.author.reload_association重新加載與該書籍關聯的作者物件, -
association_changed?:檢查關聯物件是否已更改,例如,如果您更改了與book物件關聯的author物件,則可以使用book.author_changed?檢查是否更改了該物件, -
association_previously_changed?:檢查關聯物件在上一次保存時是否已更改,例如,如果您想知道與book物件關聯的author物件在上一次保存時是否已更改,則可以使用book.author_previously_changed?檢查,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/550770.html
標籤:其他
上一篇:jdk1.8 LocalTime、LocalDate、LocalDateTime 使用大全
下一篇:返回列表
