before_filter z parametrami


84

Mam metodę, która robi coś takiego:

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

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

Chcę również użyć tej metody w niektórych innych kontrolerach, więc skopiowałem metodę do pomocnika, który jest zawarty w application_controller.

problem polega na tym, że w niektórych kontrolerach id projektu nie jest :idsymbolem, ale fe :project_id(a także :idwystępuje a (dla innego modelu)

Jak rozwiązałbyś ten problem? czy istnieje opcja dodania parametru do akcji before_filter (w celu przekazania odpowiedniego parametru)?

Odpowiedzi:


86

Zrobiłbym to tak:

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

Gdzie correct_id_herejest odpowiedni identyfikator, aby uzyskać dostęp do pliku Project.


2
czy istnieje sposób na dodanie ,:only => [:show]symbolu? before_filter { |c| c.authenticate_rights correct_id_here }, :only => [:show]
pojawia

27
Spróbuj na odwrót: before_filter(:only => [:show]) { <block_code_here> }. Więcej przykładów tutaj: apidock.com/rails/ActionController/Filters/ClassMethods/…
fguillen

1
Jeśli zabezpieczysz to przez utworzenie before_filtermetody prywatnej, a następnie możesz ponownie uwzględnić (np. Przenieść ją do kontrolera nadrzędnego, ApplicationController itp.), Będziesz musiał użyć, c.send(:filter_name, ...)ponieważ filtr nie będzie działał w kontekście kontrolera. guide.rubyonrails.org/…
Richard Michael

2
Dzięki temu filtr before_filter nie może zostać przesłonięty / pominięty z powodu braku nazwy (proc). Wartości, które chcę przekazać, to poziom klasy. Czy to jest możliwe?
oreoshake

1
@oreoshake: mam ten sam problem. Znalazłeś rozwiązanie?
marcus3006

67

Z odrobiną cukru syntaktycznego:

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

Lub jeśli zdecydujesz się na jeszcze bardziej wymyślny:

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

A ponieważ Rails 4 before_action, synonim nazwy before_filter, został wprowadzony, można to zapisać jako:

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

NB

->oznacza lambda, zwany literałem lambda , wprowadzony w Rubim 1.9

%i utworzy tablicę symboli


5
Ta odpowiedź jest bardziej elegancka, ponieważ lambda domyślnie przyjmuje kontekst wykonania klasy, stąd metody prywatne mogą być wywoływane bez użycia '.send'
David Pelaez

@Vadym Tyemirov Czy find_campaignnazwa metody prywatnej? W param=params[:id], paramczy nazwa nowej zmiennej lokalnej, która zostanie przekazana jako argument do find_campaign? Co oznacza, że w find_campaignsamej metodzie prywatnej, używamy paramnie params{:id]?
ahnbizcad

1
find_campaignmoże być albo, ale uczyniłbym to prywatnym, aby mieć pewność, że nie ujawnimy tego, co nie jest skonsumowane. paramsjest zmienną hash dostępną dla naszych metod, paramjest dowolną zmienną, którą trzeba przekazać do metody find_campaign, np.before_action ->(campaign_id=params[:id]) { find_campaign(campaign_id) }, only: %i| show edit update destroy |
Vadym Tyemirov

14

Aby kontynuować odpowiedź @alex, jeśli chcesz :exceptlub :onlyniektóre metody, oto składnia:

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

Znaleziono tutaj .


5

Uważam, że metoda blokowa używa nawiasów klamrowych zamiast do...endbyć najwyraźniejszą opcją

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

before_action jest po prostu nowszą preferowaną składnią dla before_filter


-1

To powinno działać:

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

Powinien powrócić, params[:project_id]jeśli jest obecny w hashu params, lub zwrócić, params[:id]jeśli nie jest.


problem polega na tym, że czasami oba są obecne (zagnieżdżone) i znajduje projekt, który nie jest właściwy.
wybierz

@choise: To nie powinno się zdarzyć: jeśli project_idjest obecna, orklauzula zapewni, że zostanie to użyte - tylko jeśli project_idnie zostanie idpodany parametr, zostanie wybrany. Innymi słowy: gdy podane są oba parametry, orklauzula zapewnia użycie poprawnej wartości, co zawsze będzie preferowane project_id. Oczywiście nie chcesz wywoływać tej metody, gdy żadna z nich nie jest obecna lub gdy nie ma, project_idale istnieje, idktóra nie odwołuje się do projektu.
Ola Tuvesson
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.