Rails: как установить множественные ассоциации между двумя моделями - PullRequest
1 голос
/ 09 июля 2020

У меня есть следующая связь между отзывами и пользователями:

Association

Since I'm using Devise, I kept just a single Users table and identify the roles using client or seller columns (boolean).

So as you can imagine, I need to know the user that made the review and the user being "reviewed".

The first question is: Can I make use of references while creating the migration? I manually created these columns like this: t.integer :client_id, foreign_key: true and t.integer :seller_id, foreign_key: true

The second is: How can I specify the relationship in the models? I did like this has_many :reviews, foreign_key: "client_id" and has_many :reviews, foreign_key: "seller_id" but i'm not sure if it's correct.

Here's the full code of migration:

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 Ответ

1 голос
/ 09 июля 2020

Я вижу, чего вы пытаетесь достичь.

Первым делом удалите 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_reviews и seller_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

Надеюсь, это поможет дать представление о том, что вы можете сделать.

...