before_filter з параметрами


84

У мене є метод, який робить щось подібне:

before_filter :authenticate_rights, :only => [:show]

def authenticate_rights
  project = Project.find(params[:id])
  redirect_to signin_path unless project.hidden
end

Я також хочу використовувати цей метод у деяких інших контролерах, тому я скопіював метод у помічник, який входить до складу application_controller.

проблема в тому, що в деяких контролерах ідентифікатор проекту не є :idсимволом, а fe :project_id(а також :idприсутній (для іншої моделі)

Як би ви вирішили цю проблему? чи є можливість додати параметр до дії before_filter (передати правильний параметр)?

Відповіді:


86

Я б зробив це так:

before_filter { |c| c.authenticate_rights correct_id_here }

def authenticate_rights(project_id)
  project = Project.find(project_id)
  redirect_to signin_path unless project.hidden
end

Де correct_id_hereзнаходиться відповідний ідентифікатор для доступу до Project.


2
чи є спосіб додати ,:only => [:show]символ? Я отримую помилку під час спробиbefore_filter { |c| c.authenticate_rights correct_id_here }, :only => [:show]
Choise

27
Спробуйте навпаки: before_filter(:only => [:show]) { <block_code_here> }. Інші приклади тут: apidock.com/rails/ActionController/Filters/ClassMethods/…
fguillen

1
Якщо ви захистите це, зробивши before_filterприватний метод, то, можливо, зробіть повторний коефіцієнт (наприклад, перенесіть його на батьківський контролер, ApplicationController тощо), вам потрібно буде використовувати, c.send(:filter_name, ...)оскільки фільтр не запускатиметься в контексті контролера. guides.rubyonrails.org/…
Річард Майкл

2
Це робить так, що before_filter не можна замінити / пропустити через відсутність імені (proc). Значення, які я хочу передати, - це рівень класу. Це можливо?
ореошайк

1
@oreoshake: у мене така сама проблема. Ви знайшли рішення?
marcus3006

67

З деяким синтаксичним цукром:

before_filter -> { find_campaign params[:id] }, only: [:show, :edit, :update, :destroy]

Або якщо ви вирішите захопитися ще більше:

before_filter ->(param=params[:id]) { find_campaign param }, only: %i|show edit update destroy|

А оскільки Rails 4 before_action, синонім до before_filter, був введений, то його можна записати так:

before_action ->(param=params[:id]) { find_campaign param }, only: %i|show edit update destroy|

Примітка

->розшифровується lambda, називається лямбда-літералом , введено в Ruby 1.9

%i створить масив символів


5
Ця відповідь є більш елегантною, оскільки лямбда за замовчуванням відповідає контексту виконання класу, отже, приватні методи можна викликати, не використовуючи '.send'
Девід Пелаес,

@ Вадим Тєміров Чи find_campaignназва приватного методу? В param=params[:id], це paramім'я нової локальної змінної, яка буде передана як аргумент find_campaign? Значить, що в рамках самого find_campaignприватного методу ми paramне використовуємо params{:id],?
ahnbizcad

1
find_campaignможе бути будь-яким, але я б зробив це приватним, щоб переконатися, що ми не викриваємо те, що не споживається. params- це хеш-змінна, доступна для наших методів, param- це будь-яка змінна, яку вам потрібно буде передати в метод find_campaign, наприкладbefore_action ->(campaign_id=params[:id]) { find_campaign(campaign_id) }, only: %i| show edit update destroy |
Вадим Тєміров

14

Щоб продовжити відповідь @alex ', якщо ви хочете :exceptабо :onlyдеякі методи, ось синтаксис:

before_filter :only => [:edit, :update, :destroy] do |c| c.authenticate_rights params[:id] end 

Знайдено тут .


5

Я вважаю метод блоку використанням фігурних дужок замість того, do...endщоб бути найбільш зрозумілим варіантом

before_action(only: [:show]) { authenticate_rights(id) }

before_action - це просто новий бажаний синтаксис для before_filter


-1

Це має спрацювати:

project = Project.find(params[:project_id] || params[:id])

Це повинно повернутися, params[:project_id]якщо воно присутнє в хеші параметрів, або повернутися, params[:id]якщо його немає.


проблема полягає в тому, що іноді обидва присутні (вкладені), і він знаходить проект, який не є правильним.
вибір

@choise: Цього не повинно статися: якщо project_idприсутній, orпункт буде гарантувати, що це використовується - лише якщо a project_idне вказано, idбуде вибрано параметр. Іншими словами: коли вводяться обидва параметри, orречення забезпечує правильне використання значення, як це завжди буде переважно project_id. Природно, ви не хотіли б викликати цей метод, коли жоден з них не присутній або коли його немає, project_idале є такий, idякий не посилається на проект.
Ола Тувессон,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.