Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 5 ActionCable establish stream from URL parameters

I am almost completely new to Rails, or I am sure I would know how to answer this question myself. I am just trying to modify the basic chat app created in the basic ActionCable demo: https://medium.com/@dhh/rails-5-action-cable-demo-8bba4ccfc55e#.6lmd6tfi7

Instead of having just one chat room, I want to have multiple chat rooms, so I modified my routes.rb by adding this line:

get '/rooms/show/:topic', to: 'rooms#show'

So now I can visit different chat rooms based on different topics. The rooms controller at /app/controllers/rooms_controller.rb handles these routes with no problem:

class RoomsController < ApplicationController
  def show
    @topic = params[:topic]
    @messages = Message.all
  end
end

But this parameter is not being passed to app/channels/room_channel.rb, and I'm just not sure what modifications I need to make. My current attempt:

class RoomChannel < ApplicationCable::Channel
  def subscribed
    stream_from "room_channel_#{params[:topic]}"
  end

only returns "room_channel_"

like image 580
wbruntra Avatar asked Mar 16 '16 20:03

wbruntra


2 Answers

The problem here was that I failed to understand from where the subscribed method was being called, and thus did not know how to pass parameters to it.

By reading the actioncable documentation: https://github.com/rails/rails/tree/master/actioncable

I found out that the subscribed method is called via client-side javascript, not by the rails controller. In the case of the example chat app, this means I had to change the first line of the file /app/assets/javascripts/channels/room.coffee

App.room = App.cable.subscriptions.create "RoomChannel",

to

App.room = App.cable.subscriptions.create { channel: "RoomChannel", topic: topic},

Passing a javascript object to this method allowed me to access those parameters in the subscribed method of rooms_controller.rb.

like image 97
wbruntra Avatar answered Nov 14 '22 21:11

wbruntra


Set the topic_id in a HTML tag, maybe in the body tag in your layout file.

<body data-topic-id="<%= @topic.id %>">

Now read it from JS like this:

document.querySelector('body').dataset.topicId

Your subscription creation line would look like this:

App.room = App.cable.subscriptions.create (channel: 'RoomChannel', topic_id: document.querySelector('body').dataset.topicId)
like image 26
Vaibhav Avatar answered Nov 14 '22 22:11

Vaibhav