Rails has added support in Action Cable to unsubscribe from specific stream


Rails 5 introduced Action Cable which provides WebSocket support for Rails.
It is used for creating real-time features like chat or app notifications.
It uses the Pub/Sub or Publication/Subscription process. The idea of Pub/Sub is that when an event occurs and publishes a message then the subscriber who has subscribed for that kind of message will receive the event.

Action Cable mainly consists of three things:

  • Connection
  • Channel
  • Consumer

Follow Streams

Action Cable provides two methods to create the new channel name:

  • stream_from
  • stream_for

ActionCable::Channel#stream_from

It expects a string for creating the channel.

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

This way, we can create multiple chat rooms with different names.

ActionCable::Channel#stream_for

It expects an ActiveRecord object to create the channel.

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

This will create channels specific to logged in users. Users who have subscribed to this channel will receive the message.

Thus, we can follow multiple streams by calling the above methods multiple times.

Unfollow Streams

Action Cable provides stop_all_streams method. Using this method, we can unfollow all streams at a time.

class ChatChannel < ApplicationCable::Channel
  def unsubscribed
    stop_all_streams
  end
end

The above code when triggered unsubscribes the user from all the chatrooms. What if the user just wanted to unsubscribe from a single chat room? There was no way of doing that until now.

Now, Rails has added ActionCable::Channel#stop_stream_from and ActionCable::Channel#stop_stream_for to unfollow specific stream.

ActionCable::Channel#stop_stream_from

This method expects a string similar to stream_from.

class ChatChannel < ApplicationCable::Channel
  def unsubscribed
    stop_stream_from "chat_room_#{params[:name]}"
  end
end

If a user is part of multiple chat rooms and they want to unsubscribe from one of the room then we can pass the room’s name to unsubscribe them from that specific room.

ActionCable::Channel#stop_stream_for

Similar to stream_for, it also expects an ActiveRecord object.

class ChatChannel < ApplicationCable::Channel
  def unsubscribed
    stop_stream_for room
  end
end

Here room is the object from which the user wants to unsubscribe.