I'm trying to use skip_before_filter only if the app is in production mode. (I don't want my development instances public, and I want the app to automatically detect what type of instance it is on and display a log-in screen when it is not in production mode). So, my application controller has the following line:
before_filter :authenticate_user!, :except => "sign_in" #redirects to log-in
And the controller for displaying pages has this line:
skip_before_filter :authenticate_user!, :only => :show, :if => :in_production
#public pages are public, but only when in production.
And in_production is simply:
def in_production
ENV['RAILS_ENV']=='production'
end
I realize that there may be other avenues here, but I'm curious as to why skip_before_filter seems to ignore the conditional and always just skip the before_filter. Is there something I'm missing?
It is a Rails bug (or at least an undocumented strange behaviour). It is tracked here: https://github.com/rails/rails/issues/9703
In this thread, you can find a (twisted) solution.
Instead of
skip_before_filter :authenticate_user!, :only => :show, :if => :in_production
write
skip_before_filter :authenticate_user!, :only => :show
before_filter :authenticate_user!, :only => :show, :unless => :in_production
It worked for me.
I have found that the solution posted by SmartLove in the described scenario presents a kind of security hole or an unexpected behaviour. The line
before_filter :authenticate_user!, :only => :show, :unless => :in_production
because of the :only => :show
, is overriding the existing before_filter defined in the ApplicationController. That means that all the actions of this controller (e.g :edit, :create, etc.), except the :show one, will be omitting the authenticate_user! filter.
A possible solution is removing the :only clause and checking the action called inside the conditional method. For example:
before_filter :authenticate_user!, :unless => :skip_filter?
def skip_filter?
params[:action] == "show" && in_production
end
I'm not sure skip_before_filter
accepts an :if
parameter, so I'd try this syntax
(skip_before_filter :authenticate_user!, :only => [:show]) if in_production
If it still doesn't work, try putting this in your application controller
if ENV['RAILS_ENV']=='production'
skip_before_filter :authenticate_user!, :only => :show
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With