Требуется ли proc с условным действием before_action/before_filter?

Вот, before_filter:

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

Во время недавнего обзора кода меня спросили: "Требуется ли proc для того, чтобы это работало?" Ответ, похоже, "да", но это разумный вопрос, и я намеревался ответить на него. это, обратившись к документам или руководствам Rails или чему-то еще по использованию условных выражений с before_filter (теперь псевдоним before_action).

Я не мог найти ни одного. В Руководстве по контроллеру действий упоминается :only/:except, но не :if/:unless.

В противном случае, есть ли где-нибудь в коде, на который я могу указать, что это охватывает? Это кратко упоминается здесь, но это подробнее о том, как обрабатываются :only и :except, а не :if или :unless.


person MrTheWalrus    schedule 29.04.2014    source источник


Ответы (5)


Нашел это в руководствах по Rails: http://guides.rubyonrails.org/active_record_callbacks.html#conditional-callbacks

Оказывается, Proc не всегда требуется для его работы.

параметры :if и :unless, которые могут принимать символ, строку, Proc или Array.

Так что в вашем случае вам, вероятно, сойдет с рук

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

Поиск чего-то в документации Rails иногда может быть болезненным, но, по крайней мере, такие вопросы облегчают поиск с течением времени, поскольку StackOverflow хорошо индексируется и имеет высокий рейтинг поиска.

person Dennis    schedule 08.11.2014
comment
Технически это обратные вызовы ActiveRecord, а не ActionController, но я полагаю, что синтаксис параметров такой же. Я не уверен, что строки eval'd мне нравятся больше, чем Proc, но спасибо, что нашли документы. - person MrTheWalrus; 09.11.2014
comment
Похоже, что ActionController и ActiveRecord используют одну и ту же реализацию ActiveSupport::Callbacks: api.rubyonrails.org/classes/ActiveSupport /Callbacks.html ActionController выполняет некоторую нормализацию для преобразования параметров :only и :except в параметры :if и :unless, ожидаемые ActiveSupport::Callbacks. - person adamesque; 13.12.2014

Начиная с Rails 5.2 и далее, текущий принятый ответ больше недействителен, и передача строки в условное выражение завершится ошибкой.

ПРЕДУПРЕЖДЕНИЕ ОБ УСТАРЕНИИ: Передача строки в условные параметры :if и :unless устарела и будет удалена в Rails 5.2 без замены.

Забегая вперед, процесс теперь является лучшим способом добавить условное выражение, как в исходном вопросе:

class ThingController < ApplicationController
  before_action :check_stuff, :if => proc {Rails.env.production?}
end
person Amin Shah Gilani    schedule 29.10.2017

Я сделал это в своем коде некоторое время назад. Я надеюсь, что этот пример поможет вам. Если вы можете использовать оператор if, но это должно указывать на другой метод, как я сделал здесь.

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
person jimagic    schedule 29.04.2014
comment
Это полезно знать, но не касается моего фактического вопроса о документации. - person MrTheWalrus; 29.04.2014
comment
Не будет документации о том, если и если, потому что люди используют условие внутри метода. - person jimagic; 29.04.2014
comment
Это фантастика - person Scott Hillson; 11.10.2018

Я бы рекомендовал использовать staby lambda. Если хочешь знать, ПОЧЕМУ? Пожалуйста, прочитайте это

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

что почти эквивалентно ответу Upvote Me.

person Imran Ahmad    schedule 23.03.2019

Добавление метода для проверки условий if/unless для before_action должно быть лучшим способом, так как таким образом вы сможете легко вносить любые дополнительные изменения в условия before_action в будущем:

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

  def check_stuff
  end

  private

  def check_stuff?
    Rails.env.production?
  end
end
person Sachin Singh    schedule 25.04.2021