prepend_before_action in Rails
Rails encourages usage of callbacks in controllers to execute common pieces of code before or after an action. A very simple example of this is calling the authenticate_user!
method from Devise before every action to make sure that user is authenticated.
class ApplicationController < ActionController::Base
before_action :authenticate_user!
end
But what if you want to execute a different piece of code before calling authenticate_user!
? I wanted to set a cookie based on whether the request was coming from mobile app or from web before calling authenticate_user!
. The most important thing was I wanted to set the cookie only for a particular controller action.
class MagicAuthController < ApplicationController
# Set cookie before authenticate_user! before auth
def auth
end
end
This can be solved by multiple approaches. We can create a separate base controller for MagicAuthController
and make sure the cookie is set before calling authenticate_user!
class MagicBaseController < ActionController::Base
before_action :set_cookie, only: [:auth]
before_action :autheticate_user!
end
Though Rails also provides a nifty callback called prepend_before_action
. It inserts the callback that is passed to it to the start of the callback chain.
class MagicAuthController < ApplicationController
def auth
end
end
As the MagicAuthController
inherits from the ApplicationController
the callback chain consists of authenticate_user!
as of now.
class MagicAuthController < ApplicationController
prepend_before_action :set_cookie, only: [:auth]
def auth
end
end
This changes the callback chain and now set_cookie
is the first callback in the callback chain for the auth
action.
Rails also provides other friends of prepend_before_action
such as prepend_after_action
and prepend_around_action
.
It also accepts a block argument.
prepend_before_action only: [:auth] { cookies[:clid] = params[:clid] }
Want to know more about such tricks and tips from Rails? Subscribe to my newsletter and keep up with Ruby and Rails.