Rails 的belongs_to 和has_many 的同一个模型

Posted

技术标签:

【中文标题】Rails 的belongs_to 和has_many 的同一个模型【英文标题】:Rails belongs_to and has_many of the same model 【发布时间】:2020-08-24 08:29:00 【问题描述】:

我正在尝试在 UsersCircles 两个模型之间的 rails 中创建数据库架构。圈子是一个用户定义的组,只有创建它的用户才知道。圈子包含用户选择加入该圈子的其他用户和圈子名称。

所以我的解决方案如下:

    用户模型:has_many:圈子 圈子模型:belongs_to: Userhas_many: Users

我知道存在 has_many through 方法,但我不知道这对我的情况是否有必要。

【问题讨论】:

除非您想直接从 User 访问 Users,否则不会,这听起来不像您需要的。 【参考方案1】:

您实际上需要两个不同的关联。第一个是一对多关联。设置它的懒惰方法是:

class Circle < ApplicationRecord
  belongs_to :user
end


class User < ApplicationRecord
  has_many :circles
end

这通过圈子上的外键列user_id 将用户链接到圈子。但是它非常模棱两可 - user.circles 是什么意思?是用户创建的圈子还是他所属的圈子?即使需要一些配置,也最好更明确一点:

class RenameUserToCreator < ActiveRecord::Migration[6.0]
  def change
    rename_column :circles, :user_id, :creator_id
  end
end

# rails g model circle 
class Circle < ApplicationRecord
  belongs_to :creator, class_name: 'User'
end


class User < ApplicationRecord
  has_many :created_circles, 
    class_name: 'Circle',
    foreign_key: :creator_id
end

接下来,您要向圈子添加成员。这是一个多对多关联,可以使用has_many through:has_or_belongs_to_many 完成。两者都使用连接表,但has_or_belongs_to_many 没有模型并且其实际用途非常有限。在命名连接表时,惰性约定是只使用 a 和 b 的组合 - CircleUser,但如果您能想到适合该域的名称,请使用更好的名称。

class Circle
  belongs_to :creator, class_name: 'User'
  has_many :memberships
  has_many :users, through: :memberships
end

# rails g model membership user:belongs_to circle:belongs_to
class Membership
  belongs_to :user
  belongs_to :circle
end

class User
  has_many :created_circles, 
    class_name: 'Circle',
    foreign_key: :creator_id
  has_many :memberships
  has_many :circles, through: :memberships
end

要记住的一点是,每个关联都必须有一个唯一的名称。如果我们没有经过上一步并写道:

class User
  has_many :circles
  has_many :memberships
  has_many :circles, through: :memberships
end

后一个关联只会破坏前一个关联。

【讨论】:

这正是我所需要的,并且解释得很好!一个后续问题,当我创建一个像“user1.created_circles.build”这样的圈子时,圈子表中不存在这个圈子。 “Circle.first”为零。但是 user1.created_circles 表明我有这个圈子。这是预期的吗? 是的。 build 实际上只是 new 的别名。如果您还想在一次通话中保存记录,您需要create 迁移中,改id的时候,不应该是creator_id吗? @hashrocket 是的,它应该 - 很好发现

以上是关于Rails 的belongs_to 和has_many 的同一个模型的主要内容,如果未能解决你的问题,请参考以下文章

Rails 5:将belongs_to关联与自定义名称添加到模型和迁移

Rails 查询具有 has_many 和 belongs_to 关系的模型

如何测试 belongs_to 与 Rails 6 和 RSpec 4.1 的关联?

Rails 3 中的Belongs_to 关联缓慢

Rails Searchkick / Elasticsearch has_many 和 belongs_to 关联

如何在rails 4中创建新的belongs_to关联模型