What is the difference between `stream_from` and `stream_for` in ActionCable?
Asked Answered
K

3

25

The descriptions here seem to imply that stream_for is used only when passing in a record, but overall the documentation is rather vague. Can anyone explain the differences between stream_from and stream_for and why would you use one over the other?

Keyte answered 17/8, 2016 at 16:45 Comment(0)
T
32

stream_for is simply a wrapper method of stream_from with ease.

When you need a stream that is related to a specific model, stream_for automatically generates broadcasting from the model and channel for you.

Let's assume you have a chat_room instance of ChatRoom class,

stream_from "chat_rooms:#{chat_room.to_gid_param}"

or

stream_for chat_room # equivalent with stream_from "chat_rooms:Z2lkOi8vVGVzdEFwcC9Qb3N0LzE"

the two lines of code does the same thing.

https://github.com/rails/rails/blob/master/actioncable/lib/action_cable/channel/streams.rb

Twitt answered 19/8, 2016 at 7:39 Comment(6)
What is the point of the to_gid_param part ? Couldn't you just say chat_room_#{params[:chat_room_id]} ?Kendall
Is it just for encoding an arbitrary string into a valid non-whitespace string ? Or is there any other idea behind it ?Kendall
stream_for is used when there is a particular record (or record and association) we want updates about. Under the hood, Action Cable is generating a unique string for that record or that record and its association and then calls the stream_for [sic -- probably should be 'stream_from'] method.Source: sitepoint.com/action-cable-and-websockets-an-in-depth-tutorialKendall
gid_param is hard to predict. It blocks an attacker who give random ids to get streams.Babbittry
@Kendall and how do you subscribe from the client side to a channel that you won't know in advance? I mean how do you subscribe to it?Arcuation
You can send an id as params for connection.Millepede
B
8

kevinhyunilkim's answer is almost ok, but prefix depends on channel_name, not model class.

class CommentsChannel < ApplicationCable::Channel
  def subscribed
    stream_for article
    # is equivalent to
    stream_from "#{self.channel_name}:{article.to_gid_param}"
    # in this class this means
    stream_from "comments:{article.to_gid_param}"
  end

  private

  # any activerecord instance has 'to_gid_param'
  def article
    Article.find_by(id: params[:article_id])
  end
end

you can also pass simple string to stream_for which simply adds channel name.

Babbittry answered 21/8, 2017 at 6:46 Comment(0)
A
0

stream_for takes an object as argument

class UserChannel < ApplicationCable::Channel
  def subscribed
    stream_for current_user
  end
end

stream_from takes a string as an argument

class ChatChannel < ApplicationCable::Channel
  def subscribed
    stream_from "chat_channel_#{params[:id]}"
  end
end

check this article it deals with the concept very well in my opinion

Autry answered 26/6, 2020 at 9:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.