Ответ 1
Когда вы устанавливаете before_filter
или любой подобный фильтр (подумайте after_filter
, around_filter
), вы делаете это с помощью Symbol или Proc, лямбда или блок.
before_filter :bark
before_filter Proc.new { |k| k.bark }
Приведенный выше добавляет символы или блоки в стек здесь, вызывая set_callback
. Это создает цепочку, на которую вы ссылаетесь.
Каждый элемент в этой цепочке является экземпляром класса ActiveSupport::Callbacks::Callback
. Этот класс знает
- Метод (Символ) или его блокировка должен выполняться (т.е. метод вашего класса
:bark
) - Контекст, который должен выполняться внутри (т.е. ваш класс
Dog
)
Примеры Callback
добавляются к ActiveSupport::Callbacks::CallbackChain
в __update_callbacks
.
Когда каждый Callback
класс инициализируется, _compile_filter
запускается, чтобы нормализовать фильтр из Symbol
, Proc
, lambda или block в общий, вызываемый формат.
Наконец, когда выполняется CallbackChain
, он вызывает start
для каждого экземпляра Callback
, а на данный момент, что фильтр действительно выполняется в соответствующем контексте.
Важно отметить, что не создать фильтр, например
before_filter dog.bark
он выполнит dog.bark
и передаст ему возвращаемое значение в before_filter
, которое будет добавлено к CallbackChain
. Цель состоит в том, чтобы передать некоторую инструкцию на before_filter
для Rails для последующего выполнения для вас. Вместо этого вы сделаете что-то вроде
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
делает это.
Это действительно плохой пример, потому что вы можете (и должны) просто вызвать eat
непосредственно из bark
, но это должно получить точку.