2016-10-25 6 views
2

現在の場合、recipient_idsender_idが2人のユーザー間で会話を開始する必要があります。railsチャットアプリで3人のユーザー間で会話を作成

3人目のユーザーが会話に参加することを許可したい場合、どのように関連付けが機能しますか?

ユーザーが会話を開始すると、conversation.idsender_idrecipient_idに属します。

visitor_id(これはcurrent_user)がすべての会話に参加し、すべてのユーザーがすべての会話を表示できるようにします。

conversation.rb conversation.rbモデルに

belongs_to :visitor, :foreign_key => :visitor_id, class_name: 'User' 

を追加すると、それは簡単だ場合、私は好奇心が強い

class User < ApplicationRecord 
    # Include default devise modules. Others available are: 
    # :confirmable, :lockable, :timeoutable and :omniauthable 
    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable, :validatable 


    has_many :conversations, :foreign_key => :sender_id 
    after_create :create_default_conversation 

がある

class Conversation < ActiveRecord::Base 
    belongs_to :sender, :foreign_key => :sender_id, class_name: 'User' 
    belongs_to :recipient, :foreign_key => :recipient_id, class_name: 'User' 

    has_many :messages, dependent: :destroy 

    validates_uniqueness_of :sender_id, :scope => :recipient_id 

    scope :involving, -> (user) do 
    where("conversations.sender_id =? OR conversations.recipient_id =?",user.id,user.id) 
    end 

    scope :between, -> (sender_id,recipient_id) do 
    where("(conversations.sender_id = ? AND conversations.recipient_id =?) OR (conversations.sender_id = ? AND conversations.recipient_id =?)", sender_id,recipient_id, recipient_id, sender_id) 
    end 
end 

user.rb。しかし、私は特定の会話に参加する(またはすべての会話を誰にでも見えるようにする)ためにcurrent_userに属しているvisitor_idをどのように取得できるのか分かりません。

EDIT:message.rbとコントローラを追加しました。

message.rb

class Message < ActiveRecord::Base 
    belongs_to :conversation 
    belongs_to :user 

    validates_presence_of :body, :conversation_id, :user_id 
end 

conversations_controller.rb

class ConversationsController < ApplicationController 
    before_filter :authenticate_user! 

    layout false 

    def create 
    if Conversation.between(params[:sender_id],params[:recipient_id]).present? 
     @conversation = Conversation.between(params[:sender_id],params[:recipient_id]).first 
    else 
     @conversation = Conversation.create!(conversation_params) 
    end 

    render json: { conversation_id: @conversation.id } 
    end 

    def show 
    @conversation = Conversation.find(params[:id]) 
    @reciever = interlocutor(@conversation) 
    @messages = @conversation.messages 
    @message = Message.new 
    end 

    private 
    def conversation_params 
    params.permit(:sender_id, :recipient_id) 
    end 

    def interlocutor(conversation) 
    current_user == conversation.recipient ? conversation.sender : conversation.recipient 
    end 
end 

messages_controller.rb :visitorを追加

class MessagesController < ApplicationController 
    before_filter :authenticate_user! 

    def create 
    @conversation = Conversation.find(params[:conversation_id]) 
    @message = @conversation.messages.build(message_params) 
    @message.user_id = current_user.id 
    @message.save! 

    #@path = conversation_path(@conversation) 
    end 

    private 

    def message_params 
    params.require(:message).permit(:body) 
    end 
end 
+0

会話コントローラから会話をリクエストしていますか?または、関連する会話をフェッチするためにユーザーを使用していますか?すべての会話のための会話インデックスルートを尋ねるだけであれば、そのように視覚的な会話を得ることができます。 – Pyrce

+0

追加:訪問者:最小限の変更で第三者を許可しますが、追加の第4または第k訪問者を簡単に許可しません。そのためには、すべての 'users_conversations'を追跡する結合テーブルが必要です。 – Pyrce

+0

@Pyrceあなたは正しいです。すべてのユーザーにすべての会話を表示するには、「@conversations = Conversation.all」を実行するだけです。そのようにして、どのユーザーも会話に参加して会話することができます。しかし、今問題になっているのは2人しかいないということです( 'recipient_id'と 'sender_id')ので、current_user(recipient_idとsender_idに関連付けられていない)がメッセージを送信すると、それ。 – Raidspec

答えて

2

は、最小限の変更で、第三者を可能にするが、許可しないだろう追加の第4または第k訪問者のために簡単に。これは可能性の高いシナリオと思われるので、すべてusers_conversationsを追跡する結合テーブルが必要です。

まず結合テーブルの移行を作成します。

class CreateUsersConversationsJoinTable < ActiveRecord::Migration 
    def change 
    create_table :users_conversations do |t| 
     t.integer :user_id, null: false 
     t.integer :conversation_id, null: false 
    end 
    add_index :users_conversations, [:user_id, :conversation_id], unique: true 
    end 
end 

を次にこれらの線に沿ってモデルを作成:

class UsersConversations 
    belongs_to :users, class_name: User, inverse_of: :users_conversations 
    belongs_to :conversations, class_name: Conversation, inverse_of: :users_conversations 
    validates :user_id, :conversation_id, presence: true 
end 

あなたはこのに送信者と受信者を移動させるようにしても、移行を作成する必要があるだろうニューモデル。

あなたは、送信者の属性を会話からメッセージに移動し、メッセージを使って送信者について会話にする必要があります:has_many :senders through: message, foreign_key: sender_id。そうすれば、各メッセージは送信者を追跡します。

受信者は、特定のメッセージを送信しなかった会話内のすべてのユーザーになります。あなたのメッセージクラスは、このようなものが必要になり、コメントを追加しました:

has_many :users_conversations, through: :conversations 
has_many :receivers, -> { where('users_conversations.user_id != messages.sender_id') }, through: :users_conversations, foreign_key: :user_id, class_name: 'User' 

をあなたの会話クラスはusersによって置き換えられるとあなたの範囲は次のようになります/使用する:betweenを変更する必要があるだろうが:すべて取得するには

scope :involving, -> (user) do 
    users_conversations.where(user: user) 
end 

あなたは単に関連するコントローラに@conversations = Conversation.allを割り当てるか、コントローラのインデックスルートを使用することができます。

関連する問題