环球热点评!Active Record Associations

博客园   2023-04-22 04:27:45

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  endend

这是一个创建 authorsbooks两个数据库表的迁移文件。authors表包含一个 name字段和 created_atupdated_at两个时间戳字段,books表包含一个 author_id外键字段来关联 authors表,一个 published_at字段和 created_atupdated_at两个时间戳字段。

在 Rails 中,迁移文件用于创建、修改和删除数据库表和字段。这个迁移文件中的 change方法定义了如何创建 authorsbooks两个表。在 create_table块中,我们可以声明表中的字段和类型,以及其他选项,如外键关联等。在这个例子中,我们使用 belongs_to方法来声明 books表与 authors表之间的关联关系。

当我们运行这个迁移文件时,Rails 将会执行 change方法中的代码,并在数据库中创建 authorsbooks两个表。同时,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 :profileendclass Profile < ApplicationRecord  belongs_to :userend

在上面的代码中,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_linkendclass Profile < ApplicationRecord  has_one :profile_link  has_one :user, through: :profile_linkendclass ProfileLink < ApplicationRecord  belongs_to :user  belongs_to :profileend

在上面的代码中,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 :postsendclass Post < ApplicationRecord  belongs_to :userend

在上面的代码中,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: :membershipsendclass Group < ApplicationRecord  has_many :memberships  has_many :users, through: :membershipsendclass Membership < ApplicationRecord  belongs_to :user  belongs_to :groupend

在上面的代码中,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_manyhas_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 :authorsendclass Author < ApplicationRecord  has_and_belongs_to_many :booksend

在上面的代码中,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_tohas_one是两种用于定义两个模型之间的一对一关系的方法。选择它们之间的方法取决于两个模型之间关系的性质。

当外键存储在声明关联的模型的表中时,使用 belongs_to。例如,考虑一个 Car模型,它属于一个 Manufacturer

class Car < ApplicationRecord  belongs_to :manufacturerendclass Manufacturer < ApplicationRecord  has_many :carsend

在这个例子中,cars表有一个外键 manufacturer_id引用 manufacturers表。由于外键存储在 cars表中,我们在 Car模型中使用 belongs_to来定义关联。

另一方面,当外键存储在关联模型的表中时,使用 has_one。例如,考虑一个 Person模型,它有一个 Address

class Person < ApplicationRecord  has_one :addressendclass Address < ApplicationRecord  belongs_to :personend

在这个例子中,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 :throughhas_and_belongs_to_many是两种用于定义多对多关系的方法。选择它们之间的方法取决于你是否需要在关联关系中存储其他属性。

has_many :through允许你使用中间模型来连接两个模型,并且可以在中间模型中存储其他属性。这使得 has_many :through更加灵活,适用于需要在关联关系中存储更多信息的情况。例如,考虑一个 Patient模型和一个 Doctor模型,它们之间需要建立多对多关系,而每个关联关系还需要存储一个 appointment_date属性:

class Patient < ApplicationRecord  has_many :appointments  has_many :doctors, through: :appointmentsendclass Doctor < ApplicationRecord  has_many :appointments  has_many :patients, through: :appointmentsendclass Appointment < ApplicationRecord  belongs_to :patient  belongs_to :doctorend

在上面的例子中,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 :coursesendclass Course < ApplicationRecord  has_and_belongs_to_many :studentsend

在上面的例子中,Student模型和 Course模型之间的多对多关系可以直接通过中间表建立,而不需要使用中间模型。

总之,如果你需要在关联关系中存储其他属性,应该使用 has_many :through。如果不需要存储其他属性,则可以使用 has_and_belongs_to_many来建立多对多关系。

Polymorphic Associations

在 Rails 中,多态关联(Polymorphic Associations)允许一个模型属于多个不同类型的其他模型,同时这些其他模型也可以有多个关联的模型。这种关联通常用于需要共享相同行为或属性的模型之间。

例如,考虑一个 Comment模型,它可以属于多个其他模型(例如 PostPhoto),同时这些其他模型也可以有多个评论:

class Comment < ApplicationRecord  belongs_to :commentable, polymorphic: trueendclass Post < ApplicationRecord  has_many :comments, as: :commentableendclass Photo < ApplicationRecord  has_many :comments, as: :commentableend

在上面的例子中,Comment模型使用 belongs_to方法声明了多态关联。commentable是一个多态关联字段,它可以属于任何其他模型。在 PostPhoto模型中,使用 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_tohas_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_tohas_many方法来实现 Self Joins,通过定义一个外键字段来引用自身的 ID,然后声明自身与父级的关联和自身与子级的关联。

Tips, Tricks, and WarningsControlling Caching
# retrieves books from the databaseauthor.books.load# uses the cached copy of booksauthor.books.size# uses the cached copy of booksauthor.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 :postend

然后,您需要在评论表中添加一个名为 post_id的整数列,用于存储文章的主键值。在 Rails 中,可以使用数据库迁移来添加此列:

rails generate migration AddPostIdToComments post:references

这将生成一个包含 add_reference方法的迁移文件,该方法将在评论表中添加一个 post_id列,并将其设置为引用文章表的主键。

最后,您需要运行迁移,以将更改应用于数据库:

rake db:migrate

现在,当您创建一个新评论时,Rails 将自动在评论表中设置正确的 post_id值,以引用相应的文章。

例如,您可以通过以下代码将一条评论关联到一篇文章:

post = Post.firstpost.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的表,其中 table1table2分别是要关联的两个表的名称。例如,如果您想要关联 usersgroups表,则可以创建一个名为 users_groups的联接表。

添加两个整数列,分别用于存储关联表的主键。这些列通常被命名为 table1_idtable2_id,例如 user_idgroup_id

table1table2中的模型文件中添加 has_and_belongs_to_many关联。例如,在 User模型中,您可以这样添加一个 has_and_belongs_to_many关联:

class User < ApplicationRecord  has_and_belongs_to_many :groupsend

这将指示 Rails 通过 users_groups表将 usersgroups表关联起来。

以下是一个实际的示例:

假设您正在构建一个社交网络应用程序,其中用户(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  endend

这将创建一个名为 groups_users的联接表,并添加 group_iduser_id两个整数列,用于存储关联表的主键。

最后,您可以向 UserGroup模型中添加 has_and_belongs_to_many关联,以指示它们之间的多对多关系:

class User < ApplicationRecord  has_and_belongs_to_many :groupsendclass Group < ApplicationRecord  has_and_belongs_to_many :usersend

现在,您可以使用 <<运算符向用户添加组,例如:

user = User.firstgroup = Group.firstuser.groups << group

这将将 usergroup关联起来,并在 groups_users表中添加一个新行,其中包含 user_idgroup_id的值。

通过使用 has_and_belongs_to_many关联和联接表,您可以轻松地建立多对多关系,并在 Rails 应用程序中保存和检索相关数据。

Controlling Association Scope

在 Rails 中,可以使用 scope方法来控制关联模型的查询范围。这可以帮助您过滤不必要的数据,以提高应用程序的性能和可维护性。

例如,假设您正在构建一个电子商务应用程序,其中订单(Order)有多个订单项(OrderItem),并且每个订单项都属于一个特定的产品(Product)。现在,您想要检索某个产品的所有订单项。

首先,您可以在 Product模型中添加一个 has_many关联,以指示每个产品都有多个订单项:

class Product < ApplicationRecord  has_many :order_itemsend

然后,您可以使用 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),而每个标签也可以与多篇文章相关联。为了实现这种双向关联,您可以在 PostTag模型中都定义一个关联。

首先,您可以在 Post模型中添加一个 has_and_belongs_to_many关联,以指示每篇文章都可以有多个标签:

class Post < ApplicationRecord  has_and_belongs_to_many :tagsend

然后,您可以在 Tag模型中添加一个相反的 has_and_belongs_to_many关联,以指示每个标签也可以与多篇文章相关联:

class Tag < ApplicationRecord  has_and_belongs_to_many :postsend

现在,您可以在控制器或视图中使用这些关联来访问相互关联的模型。例如,假设您想要列出所有带有特定标签的文章:

def index  @tag = Tag.find(params[:tag_id])  @posts = @tag.postsend

这将检索与 @tag相关联的所有文章,并将它们分配给 @posts变量。由于使用了双向关联,您可以通过 @tag.posts访问所有相关的文章,也可以通过 @post.tags访问所有相关的标签。

双向关联使得在两个关联模型之间进行导航变得非常容易。通过在每个模型中都定义关联,您可以轻松地访问相互关联的数据,并简化代码的编写和维护。

Detailed Association Referencebelongs_to Association Reference

这些方法都是 ActiveRecord 中用于操作关联关系的方法,主要用于设置、创建、检索和重新加载关联对象。下面是这些方法的解释:

association:获取关联对象。例如,如果 Book模型与 Author模型存在 belongs_to关联关系,则可以使用 book.author获取与该书籍关联的作者对象。

association=(associate):设置关联对象。例如,如果 Book模型与 Author模型存在 belongs_to关联关系,则可以使用 book.author = authorbook对象与特定的 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?检查。

最近更新

MORE