Question

Behold, a before_filter:

class ThingController < ApplicationController
  before_filter :check_stuff, :if => proc {Rails.env.production?}
end

During a recent code review, I was asked, "Is the proc is required for this to work?" The answer appears to be 'yes', but it's a reasonable question, and I had intended to answer it by referring to the Rails docs or guides or something on the use of conditionals with before_filter (now an alias of before_action).

I couldn't find any. The Action Controller Guide mentions :only/:except, but not :if/:unless.

Failing that, is there somewhere in the code I can point to that covers this? It's mentioned briefly here, but that's more about how :only and :except are handled, rather than :if or :unless.

Was it helpful?

Solution

Found it on Rails Guides: http://guides.rubyonrails.org/active_record_callbacks.html#conditional-callbacks

Turns out a Proc isn't always required for it to work.

the :if and :unless options, which can take a symbol, a string, a Proc or an Array.

So in your case you could probably get away with

before_action :check_stuff, if: "Rails.env.production?"

Finding things in Rails documentation can be a pain sometimes, but at least questions like this make things easier to find over time since StackOverflow is well indexed and has high search rankings.

OTHER TIPS

From Rails 5.2 onwards, the current accepted answer is no longer be valid, and passing a string to the conditional will fail.

DEPRECATION WARNING: Passing string to :if and :unless conditional options is deprecated and will be removed in Rails 5.2 without replacement.

Going forward, a proc is now the best way to add a conditional like in the original question:

class ThingController < ApplicationController
  before_action :check_stuff, :if => proc {Rails.env.production?}
end

i have done this on my code while ago. I hope that example helps to you. If you can use if statement but that should point to another method like I did here.

class Admin::ArticlesController < ApplicationController
  before_filter :deny_access, :unless => :draft_and_admin?

  def show
    @article = Article.find(params[:id])
  end

  protected

  def draft_and_admin?
    Article.find(params[:id]).draft? && current_user.admin?
  end
end

I would recommend using staby lambda. If you want know, WHY? Please read this

class ThingController < ApplicationController
  before_action :check_stuff, if: -> { Rails.env.production? }
end

which is almost equivalent to Upvote Me's answer.

Adding a method to check the if/unless conditions for a before_action should be the best way as this way you can easily accommodate any additional changes in the before_action conditions easily in future:

class ThingController < ApplicationController
  before_filter :check_stuff, if: :check_stuff?

  def check_stuff
  end

  private

  def check_stuff?
    Rails.env.production?
  end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top