當您設置一個before_filter
,或任何類似的過濾器(認爲after_filter
,around_filter
),你與無論是Symbol或Proc,拉姆達或阻止這樣做。
before_filter :bark
before_filter Proc.new { |k| k.bark }
上述追加符號或塊的堆疊here,通過調用set_callback
。這會建立你所指的'連鎖'。
此'鏈'中的每個項目都是ActiveSupport::Callbacks::Callback
類的實例。該類知道
- 的方法(符號)或阻止它必須運行(即你的類
:bark
法)
- 它必須在運行(即你的
Dog
類)上下文
Callback
實例附加到的__update_callbacks
中。
當每個Callback
類初始化,_compile_filter
運行以從Symbol
,Proc
,λ-正常化過濾器,或阻止到一個共同的,可調用的格式。
最後,在運行時CallbackChain
,它會調用start
每個Callback
實例,其在這一點上,過濾器實際上是正確的上下文中執行。
重要的是要指出的是,你會不創建一個過濾器像
before_filter dog.bark
這是要執行dog.bark
,並通過它的返回值before_filter
被附加到CallbackChain
是很重要的。其目的是爲了讓Rails稍後爲您執行某些指令而將其指令傳遞給before_filter
。你會改爲像
before_filter Proc.new { d = Dog.new; d.bark }
Proc
內的代碼不會執行。當上面的行由Rails運行時。相反,Rails被告知通過Proc
到CallbackChain
。 Proc
是您傳遞給Rails在適當的時候執行的'指令'。
如何在第一時間沒有軌道知道我呼籲:樹皮
這個,假設你的Dog
類被簡單地定義爲
class Dog
def bark
end
def eat
end
end
(雖然這是一個可怕的例子),你可能想要像
before_bark :eat
這需要你定義bark
回調,然後告訴你bark
方法來運行相關bark
回調。
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
你可以看到如何ActiveRecord::Callbacks
這樣做。
這真的是一個不好的例子,雖然因爲你可以(也應該)直接從bark
調用eat
,但這應該得到重點。
謝謝你!但仍然困惑。你說'最後,當CallbackChain運行...'時,我的問題是軌道如何知道應該運行CallbackChain?說,如果我設置了before_filter:吃課堂狗。然後,當我叫dog.bark時,應該先吃東西。但是,軌道如何知道我所稱的:樹皮? – HanXu
我更新了我的答案。 – deefour
更清晰,但仍有點困惑。在你的例子中,我們手動重新定義了樹皮,但是rails通過一些代碼自動完成。我不知道這些代碼在哪裏。根據@harald的說法,rails已經提前修改了每個動作。我注意到AbstractController :: Base中的'attr_internal',有沒有魔法發生? – HanXu