Rails: 如何在两个模型之间进行多重关联

Rails: How to multiple associations between two models

我在评论和用户之间有以下关联:

因为我使用的是 Devise,所以我只保留了一个用户 table 并使用客户或卖家列(布尔值)识别角色。

所以正如你想象的那样,我需要知道做出评论的用户和被“评论”的用户。

第一个问题是:我可以在创建迁移时使用引用吗?我像这样手动创建了这些列:t.integer :client_id, foreign_key: truet.integer :seller_id, foreign_key: true

第二个是:如何在模型中指定关系?我喜欢这个 has_many :reviews, foreign_key: "client_id"has_many :reviews, foreign_key: "seller_id" 但我不确定它是否正确。

下面是完整的迁移代码:

class CreateReviews < ActiveRecord::Migration[6.0]
  def change
    create_table :reviews do |t|
      t.text :description
      t.integer :rating, null: false
      t.integer :client_id, foreign_key: true
      t.integer :seller_id, foreign_key: true

      t.timestamps
    end
  end
end

用户模型:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  has_many :reviews, foreign_key: "client_id"
  has_many :reviews, foreign_key: "seller_id"
end

和评论模型:

class Review < ApplicationRecord
  belongs_to :user
end

Rails 版本:6.0.3.2 - Ruby 版本:2.6.6

我明白你想要达到的目标。

首先,在您的 CreateReviews 迁移中删除 foreign_key: true 因为它没有效果,您可能希望通过将其替换为 index: true.[=23 来索引这两列=]

然后在您的 User 模型中有两个不同的 has_many 关联,例如

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  has_many :client_reviews, foreign_key: "client_id", class_name: 'Review'
  has_many :seller_reviews, foreign_key: "seller_id", class_name: 'Review'
end

为什么是两个不同的协会?好吧,因为当您有两个相同的关联时,它将始终使用最后一个关联,从而覆盖第一个关联。

您可能想在您的控制台中尝试它并查看输出,对于您的情况,如果您检查查询,您将看到它正在使用 seller_id 列来查找评论,如果您尝试类似的东西。

user = User.first
p user.reviews.to_sql

现在重构您的 Review 模型,使其具有类似这样的东西

class Review < ApplicationRecord
  belongs_to :client, foreign_key: :client_id, class_name: 'User'
  belongs_to :seller, foreign_key: :seller_id, class_name: 'User'
end

现在您可以创建 client_reviewsseller_reviews 并查询每个

seller = User.create(name: 'Seller 1)
client = User.create(name: 'Client 1')

seller.seller_reviews.create(description: 'I like your product', client: client)

review = Review.first
p review.client
p review.seller

希望它能帮助您了解您的能力。