I'm using this ActionCable demo as a guideline for setting up user messaging, but I'm changing it so that there can be multiple private rooms between users. The message persists to the db through the speak
method like so [ActionCable] [me] MessagesChannel#speak({"body"=>"eee", "conversation_id"=>1})
and then calls a background worker with an after_create_commit
. The worker executes, but the broadcast is not broadcasting. What prevents that broadcast from executing?
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
views/messages/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 %>
views/messages/_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 %>
i had two lines commented out in my config/cable.yml
:
development:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
adding those back in brought my app to life