Resources

Summary

# console
brew install redis
brew services start redis

# development.rb
config.action_cable.mount_path = '/websocketier'

# application.html.erb
   <%= action_cable_meta_tag %>
   <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

# cable.js
//= require action_cable
//= require_self
//= require_tree ./channels

(function() {
  this.App || (this.App = {});

  App.cable = ActionCable.createConsumer($('meta[name=action-cable-url]').attr('content'));

}).call(this);

# console
rails g channel chat

# app/channels/chat_channel.rb
class ChatChannel < ApplicationCable::Channel
  def subscribed
    stream_from "chat"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end

# messages_controller.rb
  def create
    message = Message.create(params[:message].permit!)
    # ActionCable.server.broadcast "chat", { 
    #   message: MessagesController.render(
    #     partial: 'message', 
    #     locals: { message: message }
    #   ).squish 
    # }
  end

# message.rb
class Message < ApplicationRecord
  # after_create_commit { 
  #   ActionCable.server.broadcast "chat", { 
  #     message: MessagesController.render(
  #       partial: 'message', 
  #       locals: { message: message }
  #     ).squish 
  #   }
  # }
  
  after_create_commit { MessageBroadcastJob.perform_later(self) }
end

# console
rails g job message_broadcast

# message_broadcast_job.rb
class MessageBroadcastJob < ApplicationJob
  queue_as :default

  def perform(message)
    ActionCable.server.broadcast "chat", { message: render_message(message) }
  end

  private

  def render_message(message)
    MessagesController.render(partial: 'message', locals: {message: message}).squish
  end
end

# app/assets/javascripts/channels/chat.js
App.chat = App.cable.subscriptions.create("ChatChannel", {
  connected: function() {
    // Called when the subscription is ready for use on the server
  },

  disconnected: function() {
    // Called when the subscription has been terminated by the server
  },

  received: function(data) {
    // Called when there's incoming data on the websocket for this channel
    $('.messages').prepend(data['message']);
  },
});