Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way in Rails to skip a before_filter if the request is xhr?

With the following code :

class TestsController < ApplicationController
  skip_before_filter :load_something,      # how to skip these only 
                     :load_something_else  # if the request is xhr ?

  def index
    respond_to do |format|
      format.html
      format.js
    end
  end

end

Is there a way to skip before filters depending if the request is a javascript call without changing the :load_something and :load_something_else methods ?

Thanks !

like image 455
jrichardlai Avatar asked Feb 25 '11 07:02

jrichardlai


3 Answers

Try this line to skip the filtering by a condition:

skip_before_filter :load_something, :load_something_else,
   :if => proc { request.xhr? }

For ruby-2.0 you can also use lambdas (which have a strictness in argument passing):

skip_before_filter :load_something, :load_something_else,
   if: -> { request.xhr? }

or with an argument:

skip_before_filter :load_something, :load_something_else,
   if: ->(arg) { request.xhr? && arg }
like image 144
Малъ Скрылевъ Avatar answered Nov 18 '22 15:11

Малъ Скрылевъ


There used to be no clean solution to this. Assuming you do not have control over the before_filters (or do not want to change them), i would leave the skip_before_filter and add an extra before_filter that only executes the wanted methods if it is an xhr method.

So something like

skip_before_filter :load_something,      # how to skip these only 
                   :load_something_else  # if the request is xhr ?
before_filter :do_loads_if_xhr

def do_loads_if_xhr
  if request.xhr?
    load_something
    load_something_else
  end
end

The method described here only works because the conditional is global for the application: the conditional is only evaluated when the class is created. Not on each request.

[UPDATED] There is however, a cleaner way to make the skip_before_filter conditional. Write it like this:

skip_before_filter :load_something, :load_something_else, :if => proc {|c| request.xhr?}

Also note that while skip_before_filter is still completely supported, and not deprecated, since rails 4 the documentation seems to prefer the (identical) skip_before_action. Also the documentation is totally not clear about this, had to verify in code.

like image 39
nathanvda Avatar answered Nov 18 '22 14:11

nathanvda


All of these answers take the wrong approach in my opinion. Using a skip_before_action with a condition is doing it backwards, and isn't as explicit and clear as adding the condition to the before_action itself; so this is my proposal:

before_action :require_password_change, unless: -> { request.xhr? }

This way, to someone reading your code it's immediately clear under what conditions this before_action runs or doesn't run, without having to rely on them happening across this skip_before_action somewhere in the controller hierarchy.

like image 13
Mike Campbell Avatar answered Nov 18 '22 14:11

Mike Campbell