Есть ли способ в Rails пропустить файл before_filter, если запрос xhr?

Со следующим кодом:

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

Есть ли способ пропустить перед фильтрами, если запрос является вызовом javascript без изменения методов :load_something и :load_something_else?

Спасибо!

Ответы

Ответ 1

Раньше не было чистого решения. Предполагая, что вы не имеете контроля над before_filters (или не хотите их изменять), я бы оставил skip_before_filter и добавил дополнительный before_filter, который выполняет только нужные методы, если это метод xhr.

Так что-то вроде

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

Метод, описанный здесь, работает только потому, что условие является глобальным для приложения: условное значение оценивается только при создании класса. Не по каждому запросу.

[ОБНОВЛЕНО] Однако существует более чистый способ сделать условие skip_before_filter условным. Напишите это следующим образом:

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

Также обратите внимание, что пока skip_before_filter по-прежнему полностью поддерживается и не устаревает, поскольку рельсы 4, похоже, предпочитают (идентичные) документы skip_before_action. Кроме того, документация не совсем понятна, пришлось проверить код.

Ответ 2

Попробуйте эту строку, чтобы пропустить фильтрацию по условию:

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

Для вы также можете использовать lambdas (которые имеют строгость в передаче аргументов):

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

или с аргументом:

skip_before_filter :load_something, :load_something_else,
   if: ->(arg) { request.xhr? && arg }

Ответ 3

Все эти ответы, по моему мнению, используют неправильный подход. Использование skip_before_action с условием делает это в обратном порядке и не столь явным и ясным, как добавление условия к самому before_action; поэтому это мое предложение:

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

Таким образом, кому-то, читающему ваш код, он сразу же выясняет, при каких условиях это before_action запускается или не запускается, не полагаясь на то, что они происходят через это skip_before_action где-то в иерархии контроллера.

Ответ 4

Используйте alias_method_chain, чтобы украсить фильтры, чтобы они не выполнялись, если запрос xhr.

def load_something_with_noxhr(*args)
  load_something_without_noxhr(*args) unless request.xhr?
end

alias_method_chain :load_something, :noxhr

(измените load_something на все, что необходимо, _with_ и _without_ являются буквальными, а суффикс noxhr должен быть тем же самым, что вы передаете в качестве второго аргумента в вызове alias_method_chain.)

Ответ 5

Вы закодировали эти фильтры? В этом случае вы можете написать предложение if внутри них, не используя skip_before_filter:

def load_something
  unless request.xhr?
    #Code
  end
end

С другой стороны, вы можете сделать свой собственный фильтр и делегировать:

before_filter :my_own_filter

def my_own_filter
  unless request.xhr?
    load_something
    load_something_else
  end
end

Я думаю, что это должно сработать.