Я использую эту демонстрацию ActionCable в качестве руководства для настройки обмена сообщениями пользователей, но я меняю его, чтобы между пользователями могло быть несколько частных комнат. Сообщение сохраняется в базе данных с помощью метода speak
, например, [ActionCable] [me] MessagesChannel#speak({"body"=>"eee", "conversation_id"=>1})
, а затем вызывает фонового рабочего с after_create_commit
. Рабочий выполняется, но трансляция не транслируется. Что мешает этой трансляции?
2020-05-10T04:31:32.216Z pid=32378 tid=ouzv4m5h2 class=MessageBroadcastWorker jid=e8b23ada55bede39b811e770 INFO: start
2020-05-10T04:31:32.499Z pid=32378 tid=ouzv4m5h2 class=MessageBroadcastWorker jid=e8b23ada55bede39b811e770 elapsed=0.283 INFO: done
messages.coffee
if ($("meta[name='current-user']").length > 0)
App.messages = App.cable.subscriptions.create "MessagesChannel",
connected: ->
console.log 'Connected'
disconnected: ->
console.log 'Disconnected'
received: (data) ->
console.log 'Received'
speak: (body, conversation_id) ->
@perform 'speak', body: body, conversation_id: conversation_id
$(document).on 'turbolinks:load', ->
submit_message()
scroll_bottom()
submit_message = () ->
$('#response').on 'keydown', (event) ->
if event.keyCode is 13
conversation_id = $("#messages").data("conversation-id")
App.messages.speak(event.target.value, conversation_id)
event.target.value = ""
event.preventDefault()
scroll_bottom = () ->
if $('#messages').length > 0
$('#messages').scrollTop($('#messages')[0].scrollHeight)
messages_channel.rb
class MessagesChannel < ApplicationCable::Channel
def subscribed
#i have to change this so that the conversation id is a part of the stream but i'll do that later
stream_from "messages_channel"
end
def unsubscribed
stop_all_streams
end
def speak(data)
Message.create! body: data['body'], conversation_id: data['conversation_id'], user_id: current_user.id
end
end
message.rb
class Message < ApplicationRecord
after_create_commit { MessageBroadcastWorker.perform_async self.id }
end
message_broadcast_worker.rb
class MessageBroadcastWorker
include Sidekiq::Worker
def perform(message_id)
message = Message.find message_id
ActionCable.server.broadcast("messages_channel", message: render_message(message))
end
private
def render_message(message)
ApplicationController.renderer.render(partial: 'messages/message', locals: { message: message, username: message.user.username })
end
end
просмотров / сообщений / index. html .erb
<div id="messages" data-conversation-id="<%= @conversation.id %>">
<%= render @messages %>
</div>
<%= form_for [@conversation, @message], remote: true do |f| %>
<%= f.label :type_a_message %>
<%= f.text_area :body, placeholder: "Say something.", autofocus: true, id:"response" %>
<% end %>
просмотров / сообщений / _message. html .erb
<% cache message do %>
<div class="message">
<div><strong><%= message.user.username %>:</strong> <%= message.body %></div>
<div class="date"><%= local_time(message.created_at) %></div>
</div>
<% end %>