How to create multiple channels using Actioncable; how to pass in-document variable to javascript and ruby ​​channels and jobs?

For example, at https://www.youtube.com/watch?v=n0WUjGkDFS0 at 10:36, he mentions the possibility of creating multiple channels, but how to actually do it

According to Rails 5, an ActionCable sets a stream from URL parameters. A variable can be defined and passed as a parameter, for example:

def subscribed stream_from "room_channel_#{params[:roomId]}" end 

But in a javascript file before transferring data here, how does one transfer data from the page? The following example displays an error because the cable is presumably detected prior to loading the document.

 App.room = App.cable.subscriptions.create { channel: "RoomChannel", roomId: document.getElementById("message_text").getAttribute("data-room")} 

Then, if you can get the data from the document into a variable here and pass it to the stream_from method, then finally, how is the right channel passed to the execution method that will be used in the broadcast task?

  def perform(message) ActionCable.server.broadcast 'room_channel_???', message: render_message(message) #, roomId: roomId end 

Thanks!

+5
source share
2 answers

I learned a lot by looking at the ActionCable example . I, too, was embarrassed by the documents that offer parsing options and start streaming playback immediately by subscription. Although this is an option , you may prefer the approach below.

Create a special method that can be called from the client side (JS), for example start_listening :

 class RoomChannel < ApplicationCable::Channel # Called when the consumer has successfully # become a subscriber of this channel. def subscribed end def start_listening room_data stop_all_streams # optional, you might also keep listening... stream_for Room.find(room_data['room_id']) end def stop_listening stop_all_streams end end 

With this code (and server restart) you can now call the following line when you really loaded the room:

 App.roomChannel.perform("start_listening", {room_id: 20}); 

Now you can transfer data to the room anywhere using broadcast_to . For instance. from RoomMessage after_safe -action:

 RoomChannel.broadcast_to(room, room_message) 

This will send a message to everyone who is listening.

Separating the moment you start listening to a stream from the actual opening of the connection, it is easier to configure several data streams (there is one connection that can have many channels, which can have many streams) (just do not close the old streams when starting a new one;)). The connection setup time will also be a little faster, although this is usually due to the price of having an open connection, possibly after the user logs in, which you can easily bypass by signing up immediately before listening.

+2
source

I came up with 2 solutions to this problem.

  • This type is illogical - you can just parse the URL. You always want the part after the last "/", so thanks to REST this is a viable option.
  • One is better - you can transfer all of your client subscription code to the function that is called when the document is loaded. Thus, you have all the data from the available page to create a new subscription.

Hope you answer if you find a cleaner solution.

0
source

Source: https://habr.com/ru/post/1247696/


All Articles