【问题标题】:Rails: How to multiple associations between two modelsRails:如何在两个模型之间进行多重关联
【发布时间】:2020-07-09 08:08:18
【问题描述】:

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

由于我使用的是 Devise,我只保留了一个用户表,并使用客户或卖方列(布尔值)来识别角色。

所以你可以想象,我需要知道进行评论的用户和被“评论”的用户。

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

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

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

    首先,在您的CreateReviews 迁移中删除foreign_key: true,因为它没有任何效果,您可能希望通过将其替换为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
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多