2013-09-03 15 views
19

W jakiej kolejności robisz przed filtrami? W szczególności, w jakiej kolejności występują filtry before_action w odniesieniu do inheiritance? Na przykład czy to zadziała:W jakiej kolejności robisz przed filtrami?

class A < ActionController::Base 
    before_action :set_user 

    def set_user 
    @user = something 
    end 
end 

class B < A 
    before_action :set_post 

    def show 
    render @post 
    end 

    def set_post 
    @post = @user.posts.first 
    end 
end 

Czy "B # pokaż" działa? Jakie są zasady dotyczące kolejności filtrowania na przyszłość? Nie mogę znaleźć tego w dokumentacji Railsów.

+0

Czy twoja klasa '' 'A''' nie dziedziczy po niektórych kontrolerach takich jak * ActionController *? Jeśli akcja jest wykonywana na instancji '' 'B''', to odziedziczone filtry takie jak' '' set_user''' są nazywane jako pierwsze. –

+0

Przepraszam za to. Naprawione. –

+0

, jak naprawić zamówienie: http://stackoverflow.com/questions/5711797/how-can-i-specify-the-order-that-before-filters-are-ex-edecuted –

Odpowiedz

19

Proponuję przyjrzeniu the source code i API Docs na filtrach.

Domyślna kolejność powinna być

  1. :set_post
  2. :set_user

Myślę, że jeśli chciał pchnąć :set_user na szczycie stosu można zmienić linię w A do

prepend_before_action :set_user 

Warto również podkreślić, że nie jest to jedyne pytanie na ten temat; są others here on SO.


Co do konkretnej sytuacji, wygląda na to trzeba zmienić A jak już wspomniano powyżej, aby mieć @user być przypisana do czasu set_post w B przebiegów.


Począwszy od 4.2.6 (prawdopodobnie zmieniła we wcześniejszej wersji), kolejność jest teraz przed rodzicem dziecka:

  1. :set_user
  2. :set_post
+1

Dzięki. Tego właśnie potrzebowałem. –

+0

Masz domyślną kolejność (powyżej) w tył. Przedfuntery przed klasy pochodnej (B) są wywoływane przed klasą podstawową (A) przed_filtrami. Tak więc jest: 1.: set_user i 2.: set_post Należy również zwrócić uwagę, że after_filters są wywoływane w odwrotnej kolejności, najczęściej wyprowadzane jako pierwsze. –

+6

Właśnie próbowałem tego na Railsach 4.2 i wygląda na to, że to już nie jest poprawne. Wywołanie klasy macierzystej jest wykonywane najpierw, a następnie oddzwanianie klasy dziecka. A więc: 1) 'set_user', 2)' set_post' – head

0

Tak, Twój kod będzie działać zgodnie z przeznaczeniem.

Przedfiltry przed klasa pochodna (B) są wywoływane przed before_filters w klasie bazowej (A). Więc kolejność metod zwanych są:

  1. set_user()
  2. set_post()
  3. pokaz()

Należy również pamiętać, after_filters nazywane są w odwrotnej kolejności, najbardziej pochodzi pierwszy .

+2

Jak już powiedziałeś, filtr before_filter w klasie pochodnej jest nazywany pierwszym, ponieważ B jest klasą pochodną, ​​set_post zostanie wywołany jako pierwszy, a następnie set_user. – DallaRosa

5

Przyjęta odpowiedź nie jest już zgodna z wersją 4.2.6. Najprawdopodobniej została zmieniona wcześniej, ale to jest wersja, w której teraz jestem.

filtry rodzicielskie są teraz nazywane przed filtrami dzieci, więc kolejność będzie teraz:

  1. :set_user
  2. :set_post

A jeśli myślisz o tym, że zamawianie naprawdę sprawia więcej sens. Jak wcześniej wspomniano, jeśli potrzebujesz, aby dziecko wywołało filtr przed rodzicem, musisz użyć prepend_before_action.