Есть ли способ, чтобы две таблицы объединения связывали одни и те же два класса в приложении rails?

#ruby-on-rails #rails-activerecord #rails-migrations

#ruby-on-rails #рельсы-activerecord #rails-миграции #rails-activerecord

Вопрос:

Давний слушатель, вызывающий в первый раз. Я пытаюсь создать две ассоциации между одними и теми же таблицами базы данных, комнатами чата и пользователями. Пока у меня есть отношение has_many through, при котором в комнате чата много пользователей через сообщения. Эта часть работает нормально. Что я хочу сделать, это создать вторую таблицу объединения, которая соединяет комнаты чата с пользователями, через таблицу объединения, называемую Chatroom_players. Итак, я бы хотел, чтобы Chatroom.first.users приводил мне пользователей через таблицу объединения сообщений, а Chatroom.first.players — всех из таблицы объединения chatroom_players. Причина, по которой я хочу этого, заключается в том, что я могу поддерживать присутствие пользователя, даже если пользователь не написал никаких сообщений в чате, также чтобы пользователь мог покинуть комнату, но сохранить свои сообщения в чате.

Вот что у меня пока что не работает:

chatroom.rb:

 class Chatroom < ApplicationRecord
  has_many :messages, dependent: :destroy
  has_many :users, through: :messages

  has_many :chatroom_players
  has_many :users, through: :chatroom_players
end
  

message.rb:

 class Message < ApplicationRecord
  belongs_to :chatroom
  belongs_to :user
  validates :content, presence: true, length: {minimum: 2, maximum: 200}
end
  

chatroom_player.rb

 class ChatroomPlayer < ApplicationRecord
  belongs_to :chatroom
  belongs_to :user
end
  

user.rb

 class User < ApplicationRecord
  has_many :messages, dependent: :destroy
  has_many :chatrooms, through: :messages

  has_many :chatroom_players
  has_many :chatrooms, through: :chatroom_players
end
  

миграция chatroom_players:

 class AddChatroomPlayers < ActiveRecord::Migration[5.0]
  def change
    create_table :chatroom_players do |t|
      t.references :user, index: true, foreign_key: true, null: false
      t.references :chatroom, index: true, foreign_key: true, null: false
      t.boolean :creator, default: false
      t.timestamps null: false
    end
  end
end
  

Ответ №1:

Вам нужно использовать разные имена для ассоциаций:

 class Chatroom < ApplicationRecord
  has_many :messages, dependent: :destroy
  has_many :users, through: :messages
  has_many :chatroom_players
  # this is a separate association to users through the
  # chatroom_players table.
  has_many :participants, 
     through: :chatroom_players, 
     source: :user, # what association on chatroom_players to use
     class_name: 'User' # since it cannot be deduced automatically
end
  

Комментарии:

1. guides.rubyonrails.org/…

2. Отличный ответ, спасибо! Еще одна вещь, которую мне нужно было сделать, что я и сделал в вашем стиле, это связать комнаты чата с пользователями как игры, так что теперь у пользователей есть игры и комнаты чата, а в комнатах чата есть пользователи и игроки.

3. has_many : games, через: :chatroom_players, source: : chatroom, class_name: «Чат»