Skip_before_filter игнорирует условные обозначения

Я пытаюсь использовать skip_before_filter только в том случае, если приложение находится в рабочем режиме. (Я не хочу, чтобы мои экземпляры разработки были общедоступны, и я хочу, чтобы приложение автоматически определяло, какой тип экземпляра он включен, и отображает экран входа в систему, когда он не находится в рабочем режиме). Итак, мой контроллер приложений имеет следующую строку:

before_filter :authenticate_user!, :except => "sign_in" #redirects to log-in

И контроллер для отображения страниц имеет следующую строку:

skip_before_filter :authenticate_user!, :only => :show, :if => :in_production
#public pages are public, but only when in production.

И in_production просто:

  def in_production
    ENV['RAILS_ENV']=='production'
  end

Я понимаю, что здесь могут быть другие возможности, но мне любопытно, почему skip_before_filter, похоже, игнорирует условное и всегда просто пропускает before_filter. Что-то мне не хватает?

Ответы

Ответ 1

Это ошибка Rails (или, по крайней мере, недокументированное странное поведение). Отслеживается здесь: https://github.com/rails/rails/issues/9703

В этом потоке вы можете найти (скрученное) решение.

Вместо

skip_before_filter :authenticate_user!, :only => :show, :if => :in_production

записи

skip_before_filter :authenticate_user!, :only => :show
before_filter      :authenticate_user!, :only => :show, :unless => :in_production

Это сработало для меня.

Ответ 2

Я обнаружил, что решение, отправленное SmartLove в описанном сценарии, представляет собой своего рода дыру в безопасности или неожиданное поведение. Строка

before_filter :authenticate_user!, :only => :show, :unless => :in_production

из-за :only => :show, переопределяет существующий before_filter, определенный в ApplicationController. Это означает, что все действия этого контроллера (например: edit,: create и т.д.), За исключением: show one, будут опущены authenticate_user! фильтр.

Возможным решением является удаление предложения: only и проверка действия, вызываемого внутри условного метода. Например:

before_filter :authenticate_user!, :unless => :skip_filter?

def skip_filter?
  params[:action] == "show" && in_production
end

Ответ 3

Я не уверен, что skip_before_filter принимает параметр :if, поэтому я бы попробовал этот синтаксис

(skip_before_filter :authenticate_user!, :only => [:show]) if in_production

Если он по-прежнему не работает, попробуйте поместить его в контроллер приложения

if ENV['RAILS_ENV']=='production'
  skip_before_filter :authenticate_user!, :only => :show
end