Rails:如何在两个模型之间建立多重关联

时间:2020-07-09 08:08:18

标签: ruby-on-rails activerecord

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

statement

自从我使用Devise以来,我只保留了一个Users表,并使用客户或卖方列(布尔值)来标识角色。

如您所想,我需要知道进行评论的用户和正在“评论”的用户。

第一个问题是:在创建迁移时可以使用引用吗?我手动创建了以下列: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

1 个答案:

答案 0 :(得分:1)

我明白了您要达到的目标。

首先,在foreign_key: true迁移中删除CreateReviews ,因为它没有效果,您可能希望通过用index: true替换这两个列来建立索引。

然后在您的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

希望它可以帮助您了解您可以做什么。

相关问题