August 2, 2022
This blog is part of our Rails 7 series.
Action Cable allows us to add callbacks for individual channels. These are:
after_subscribe
, after_unsubscribe
, before_subscribe
,
before_unsubscribe
, on_subscribe
, on_unsubscribe
. These callbacks are
registered individually for each Channel. Before Rails 7.1, there was no way in
which we could register callbacks to be called before every command generically.
Rails 7.1 solves this problem by providing a set of callbacks which can be
registered at the connection level. And these callbacks are called for every
command regardless of which channel's command is being invoked.
These are the following callbacks which can be registered:
before_command
: This callback is invoked before any command can be
processed by the channel.around_command
: This callback is generally invoked around the command. Any
piece of code before yield
is run before the actual command and any piece
of code after yield
is run after the command has been processed by the
channel.after_command
: This callback is invoked after the command has been
processed by the channel.Let's take a look at some example code to understand this behaviour better:
class Connection < ActionCable::Connection::Base
identified_by :current_user
before_command :set_current_user
around_command :register_telemetry_data
after_command :update_current_user
private
def set_current_user
if request.params["user_id"].present?
self.current_user = User.find_by(request.params["user_id"])
end
reject_unauthorized_connection if self.current_user.nil?
end
def register_telemetry_data
self.current_user.register_telemetry({ start: true })
yield
self.current_user.register_telemetry({ end: true })
end
def update_current_user
self.current_user.touch(:updated_at)
end
end
Here, we can expect set_current_user
to be invoked before every command is
processed. Similar to this, we can also expect update_current_user
to be
invoked after every command is processed. Where as for the
register_telemetry_data
,
self.current_user.register_telemetry({ start: true })
is run before the
command is processed and then after the command is processed,
self.current_user.register_telemetry({ end: true })
is run.
Please check out this pull request for more details.
If this blog was helpful, check out our full blog archive.