Ruby on Rails 5 Action Cable: stream for current model instance (URL-based subscriptions)
Asked Answered
A

2

10

I have searched the web far and wide (including reading many code examples for ActionCable) for what seems to be an answer to a very basic question. Alas, I have not solved my problem.

Suppose, I have a model Search and I have navigated to the URL /searches/1.

I would also have the search.coffee file under javascripts/channels/ which starts with:

App.instance = App.cable.subscriptions.create 'SearchChannel'

and a SearchChannel class that looks like this:

class SearchChannel < ApplicationCable::Channel
  def subscribed
    search = Search.find(params[:id])
    stream_for search
  end

  def unsubscribed
  end
end

Naturally, the code above produces an error because params[id] is nil.

Here are my questions:

  • How do I subscribe to the correct Search instance based on the URL?
  • How do I avoid trying to subscribe to SearchChannel if I am on another URL that doesn't require a subscription, e.g. /searches/1/results?

Thank you for help!

Abebi answered 26/8, 2016 at 18:6 Comment(2)
Hi, Please mark my answer as the correct one if it has helped you out.Substantiate
So far none of the answers has helped me out, @VaibhavMaheshwari.Abebi
E
0

If you look at implementation of ActionCable.Subscriptions#create, it can be called in two ways.

Option 1 (with channelName):

App.cable.subscriptions.create 'SearchChannel'

Option 2 (with channel Object):

App.cable.subscriptions.create channel: 'SearchChannel', id: 'Best Room'

If you go with Option 1, internally, it gets converted into channel Object.

So, if you want to capture id on the server side, you need to use the 2nd option and pass the id of the search, then you should be able to capture it on the server side as you described:

class SearchChannel < ApplicationCable::Channel
  def subscribed
    search = Search.find(params[:id])
    stream_for search
  end

  def unsubscribed
  end
end

Refer to Client-Server Interactions and Subsciptions for more info.

Equi answered 2/9, 2016 at 22:21 Comment(2)
Thank you for your answer, but this doesn't help me. I had already read about this option in the documentation, but what I am confused about is specifically how to send that id to the SearchChannel. Rails puts search.coffee under javascripts/channels/, which means I need to pass that id from somewhere to that file. That's where my difficulty lies.Abebi
I am not quite sure what you were trying to achieve with SearchChannel subscription. But if you need to capture the @search.id from the ruby side to the javascript side, you have multiple options. Option1: While you are at /searches/1 url, you could parse the url in javascript and pass the id from the url to App.cable.subscriptions.create. Option2: In the head of the show template, store the id in javascript, for ex: <%= javascript_tag "var search_id = #{params[:id]}" %> and pass that search_id to App.cable.subscriptions.create. Hope that helps.Equi
S
0

Hello if you need to access the variables from the URL for server side handling of the connections, here is what you can do. In your search.coffee.erb file.

string = window.location.href 
cut_string = "/"
if string.indexOf(cut_string) != -1 
    id = string.split(cut_string)[4]
else
    id = // something else

App.instance = App.cable.subscriptions.create { channel: "SearchChannel" , id: id } , ...

In your channel file, you can succesfully use it.

class SearchChannel < ApplicationCable::Channel
  def subscribed
    search = Search.find(params[:id])
    stream_for search
  end

  def unsubscribed
  end
end

How do I subscribe to the correct Search instance based on the URL?

You can change the coffeescript code and make it so that it only creates an actioncable connection if the desired page is browsed.

string = window.location.href 
cut_string = "/"
if string.indexOf(cut_string) != -1 
    id = string.split(cut_string)[4] IF BLOCK CREATE CONNECTION
    App.instance = App.cable.subscriptions.create { channel: "SearchChannel" , id: id } , ...

How do I avoid trying to subscribe to SearchChannel if I am on another URL that doesn't require a subscription, e.g. /searches/1/results

Add multiple conditions to the if block in the coffescript code.

Substantiate answered 22/6, 2018 at 23:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.