Rails: Before process_action callback :authenticate_user! has not been defined

I had a similar issue to this when I was working on a Rails 6 application with Devise gem for authentication and authorization.

I added a skip_before_action :authenticate_admin!, only: [:index, :show] to the Products controller

class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]
  skip_before_action :authenticate_admin!, only: [:index, :show]

  def index
    @products = Product.all
  end
  .
  .
  .
end

And it was throwing the error below when I visit the Products page:

Before process_action callback :authenticate_admin! has not been defined

Here's how I fixed it:

To use the skip_before_action :authenticate_admin!, only: [:index, :show] in the Products controller, I first needed to define the before_action :authenticate_user! in the application_controller:

# app/controllers/application_controller.rb:

class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception

  before_action :authenticate_admin!

end

Now I can use the skip_before_action :authenticate_admin!, only: [:index, :show] in the Products controller:

class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]
  skip_before_action :authenticate_admin!, only: [:index, :show]

  def index
    @products = Product.all
  end
  .
  .
  .
end

An alternative, if I don't want to define the before_action :authenticate_user! in the application_controller is to use the before_action :authenticate_admin!, except: [:index, :show]:

class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_admin!, except: [:index, :show]

  def index
    @products = Product.all
  end
  .
  .
  .
end

That's all.

I hope this helps


Twilio developer evangelist here.

It looks like this was a problem that Rails 5 seems to have introduced. If the filter hasn't been defined by the time it is used in a controller it will raise an error. This was discovered in the Clearance project too.

Their fix was to pass the raise: false option to skip_before_filter:

class MessagesController < ApplicationController
  skip_before_filter :verify_authenticity_token 
  skip_before_filter :authenticate_user!, :only => "reply", :raise => false

end