Quando si imposta un before_filter
, o qualsiasi filtro simile (pensare after_filter
, around_filter
), si sta facendo in modo sia con un Symbol o un Proc, lambda o il blocco.
before_filter :bark
before_filter Proc.new { |k| k.bark }
che questo aggiunge i simboli o blocchi di una pila here, chiamando set_callback
. Questo costruisce la "catena" a cui ti stai riferendo.
Ogni elemento in questa 'catena' è un'istanza della classe ActiveSupport::Callbacks::Callback
. Questa classe sa
- Il metodo (Symbol) o bloccare deve eseguire (es. La classe
:bark
metodo)
- Il contesto cui deve funzionare entro (es. La classe
Dog
)
I Callback
istanze sono aggiunti ad un ActiveSupport::Callbacks::CallbackChain
in __update_callbacks
.
Quando ciascuna classe Callback
è inizializzato, _compile_filter
viene eseguito per normalizzare il filtro dal Symbol
, Proc
, lambda, o bloccare in un formato comune, richiamabile.
Infine, quando il CallbackChain
viene eseguito, chiamerà start
su ogni Callback
istanza e suo a questo punto che il filtro sia effettivamente eseguito nel contesto corretto.
E 'importante sottolineare che si non creare un filtro come
before_filter dog.bark
questo sta per eseguire dog.bark
e passare il suo valore di ritorno per before_filter
da aggiungere al CallbackChain
. L'intenzione è di passare una sorta di istruzione su before_filter
affinché Rails possa essere eseguito successivamente per te. Si potrebbe invece fare qualcosa di simile
before_filter Proc.new { d = Dog.new; d.bark }
Il codice all'interno del Proc
non viene eseguito. quando la linea di cui sopra è gestita da Rails. Invece, a Rails viene richiesto di passare lo Proc
allo CallbackChain
. Lo Proc
è l''istruzione' che stai trasmettendo a Rails da eseguire al momento opportuno.
come in primo luogo fa rotaie sa che ho chiamato: corteccia
Per quanto riguarda questo, diciamo che la classe Dog
è semplicemente definito come
class Dog
def bark
end
def eat
end
end
(Anche se questo è un terribile esempio), potresti voler avere qualcosa come
before_bark :eat
Ciò richiede di definire il bark
richiamata, e poi dire il metodo bark
per eseguire i relativi bark
callback.
class Dog
extend ActiveModel::Callbacks
define_callbacks :bark
before_bark :eat
def bark
run_callbacks(:bark) { YOUR BARK CODE HERE }
end
def eat
end
end
si può vedere come ActiveRecord::Callbacks
fa questo.
Questo è davvero un cattivo esempio, anche perché è possibile (e dovrebbe) solo chiamare eat
direttamente da bark
, ma questo dovrebbe ottenere il punto attraverso.
Grazie a prima vista! Ma ancora confusione. Hai detto 'Finalmente, quando viene lanciato CallbackChain ...', e la mia domanda è esattamente come fa sapere a rails che CallbackChain dovrebbe essere lanciato? Dimmi, se imposto before_filter: mangia in classe Dog. Quindi quando chiamo dog.bark,: mangiare dovrebbe essere eseguito prima. Ma, come in primo luogo i binari sanno che ho chiamato: corteccia? – HanXu
Ho aggiornato la mia risposta. – deefour
Molto più chiaro, ma ancora un po 'confuso. Nel tuo esempio, ridefiniamo manualmente la corteccia, ma le rotaie lo fanno automaticamente con del codice. Non trovo dove si trovano questi codici. Secondo @harald, le rotaie hanno modificato ciascuna azione in anticipo. Ho notato 'attr_internal' in AbstractController :: Base, c'è la magia? – HanXu