###やりたいこと
複数モデル(users/model_users)を作成し、一つのroomチャンネルで双方向でチャットさせたい。
1.user or model_usersでログイン
2.roomを作成しチャットルームに入る
3.フォームに投稿
4.messagesテーブルに保存 <- ここでエラー
###つまってる箇所
1.投稿したときにバリデーションがかかり、投稿できない(messagesテーブルに保存時)
2.二つ目のモデルのidがnilの場合エラーが起きる
3.params'room'の取得もうまくいってない?かも?
room_channnel.rb内でbinding.pryをし、
[1] pry(#<RoomChannel>)> params => {"channel"=>"RoomChannel"}
と返ってきて、params['room']もうまくいってないのではないか?
###エラー文
Could not execute command from ({"command"=>"message", "identifier"=>"{\"channel\":\"RoomChannel\"}", "data"=>"{\"message\":\"kkkkk\",\"action\":\"speak\"}"}) [ActiveRecord::InvalidForeignKey - Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails (`xxxxxxxx_development`.`messages`, CONSTRAINT `fk_rails_7d0ceb7a67` FOREIGN KEY (`model_user_id`) REFERENCES `model_users` (`id`))]
###該当コード
room_channnel.rb
class RoomChannel < ApplicationCable::Channel def subscribed stream_from "room_channel_#{params['room']}" end def unsubscribed # Any cleanup needed when channel is unsubscribed end def speak(data) # jsで実行されたspeakのmessageを受け取り、room_channelのreceivedにブロードキャストする # ActionCable.server.broadcast 'room_channel', message: data['message'] # Message.create! content: data['message'] Message.create! content: data['message'], user_id: current_user.id, room_id: params['room'], model_user_id: nil end end
room_channnel.js
import consumer from "./consumer" $(function(){ const chatChannel = consumer.subscriptions.create({ channel: 'RoomChannel', room: $('#messages').data('room_id') }, { connected() { // Called when the subscription is ready for use on the server }, disconnected() { // Called when the subscription has been terminated by the server }, // room_channel.rbでブロードキャストされたものがここに届く received: function(data) { return $('#messages').append(data['message']); }, // これが実行されるとコンシューマになったRoomChannel#speak({ message: message })が呼ばれる speak: function(message) { return this.perform('speak', { message: message }); } }); $(document).on('keypress', '[data-behavior~=room_speaker]', function(event) { if (event.keyCode === 13) { chatChannel.speak(event.target.value); event.target.value = ''; return event.preventDefault(); } }); });
model/message.rb
class Message < ApplicationRecord validates :content, presence: true # createの後にコミットする { MessageBroadcastJobのperformを遅延実行 引数はself } after_create_commit { MessageBroadcastJob.perform_later self } belongs_to :user belongs_to :model_user belongs_to :room end
###参考にしたサイト
https://qiita.com/eRy-sk/items/4c4e983e34a44c5ace27
###バージョン
Rails 6.0.3.2
あなたの回答
tips
プレビュー