Spec-Zone.ru › Ruby on Rails 4.1

модуль ActiveSupport::Callbacks::ClassMethods

Публичные методы экземпляров

define_callbacks(*names) Показать исходный код

Определяет наборы событий в жизненном цикле объекта, поддерживающих обратные вызовы.

define_callbacks :validate
define_callbacks :initialize, :save, :destroy
Параметры
  • :terminator - Определяет, когда фильтр перед обратным вызовом прервёт цепочку обратных вызовов, предотвращая вызов последующих обратных вызовов и событие не будет срабатывать. Это должна быть лямбда-функция, которая должна быть выполнена. Текущий объект и результат возвращаемого вызова обратного вызова будут переданы лямбде.

    define_callbacks :validate, terminator: ->(target, result) { result == false }
    

    В этом примере, если любой обратный вызов перед валидацией возвращает false, другие обратные вызовы не выполняются. По умолчанию false, что означает, что ни одно значение не прерывает цепочку.

  • :skip_after_callbacks_if_terminated - Определяет, будут ли обратные вызовы после прекращены параметром :terminator. По умолчанию, обратные вызовы после выполняются независимо от того, была ли прервана цепочка обратных вызовов или нет. Параметр имеет смысл только при указании параметра :terminator.

  • :scope - Указывает, какие методы должны выполняться, когда объект используется в качестве обратного вызова.

    class Audit
      def before(caller)
        puts 'Audit: before is called'
      end
    
      def before_save(caller)
        puts 'Audit: before_save is called'
      end
    end
    
    class Account
      include ActiveSupport::Callbacks
    
      define_callbacks :save
      set_callback :save, :before, Audit.new
    
      def save
        run_callbacks :save do
          puts 'save in main'
        end
      end
    end
    

    В приведенном выше случае, каждый раз при сохранении учетной записи, будет вызываться метод Audit#before. С другой стороны

    define_callbacks :save, scope: [:kind, :name]
    

    будет вызывать Audit#before_save вместо. Это создается путём вызова #{kind}_#{name} для данного экземпляра. В этом случае «kind» - это «перед», а «name» - «сохранить». В этом контексте :kind и :name имеют особое значение: :kind относится к типу обратного вызова (перед/после/вокруг), а :name относится к методу, для которого определяются обратные вызовы.

    Объявление подобное

    define_callbacks :save, scope: [:name]
    

    будет вызывать Audit#save.

# File activesupport/lib/active_support/callbacks.rb, line 761
def define_callbacks(*names)
  options = names.extract_options!
  if options.key?(:terminator) && String === options[:terminator]
    ActiveSupport::Deprecation.warn "String based terminators are deprecated, please use a lambda"
    value = options[:terminator]
    line = class_eval "lambda { |result| #{value} }", __FILE__, __LINE__
    options[:terminator] = lambda { |target, result| target.instance_exec(result, &line) }
  end

  names.each do |name|
    class_attribute "_#{name}_callbacks", instance_writer: false
    set_callbacks name, CallbackChain.new(name, options)
  end
end
reset_callbacks(name) Показать исходный код

Удаляет все установленные обратные вызовы для данного события.

# File activesupport/lib/active_support/callbacks.rb, line 681
def reset_callbacks(name)
  callbacks = get_callbacks name

  ActiveSupport::DescendantsTracker.descendants(self).each do |target|
    chain = target.get_callbacks(name).dup
    callbacks.each { |c| chain.delete(c) }
    target.set_callbacks name, chain
  end

  self.set_callbacks name, callbacks.dup.clear
end
set_callback(name, *filter_list, &block) Показать исходный код

Устанавливает обратный вызов для данного события.

set_callback :save, :before, :before_meth
set_callback :save, :after,  :after_meth, if: :condition
set_callback :save, :around, ->(r, &block) { stuff; result = block.call; stuff }

Второй аргумент указывает, должен ли обратный вызов быть выполнен :before, :after, или :around событие. Если он опущен, предполагается :before. Это означает, что первый пример выше также может быть записан как:

set_callback :save, :before_meth

Обратный вызов может быть задан как символ, обозначающий метод экземпляра; как proc, lambda или блок; как строка, которая будет вычисляться в контексте экземпляра; или как объект, который отвечает на определенный метод, определяемый аргументом :scope для define_callbacks.

Если задан proc, lambda или блок, его тело вычисляется в контексте текущего объекта. Он также может необязательно принимать текущий объект в качестве аргумента.

Обратные вызовы перед и вокруг вызываются в порядке, в котором они устанавливаются; обратные вызовы после вызываются в обратном порядке.

Обратные вызовы вокруг могут получить значение возврата от события, если оно не было остановлено, из вызова yield.

Параметры
  • :if - Символ, обозначающий метод экземпляра или proc; обратный вызов будет вызван только тогда, когда он возвращает true значение.

  • :unless - Символ, обозначающий метод экземпляра или proc; обратный вызов будет вызван только тогда, когда он возвращает false значение.

  • :prepend - Если true, обратный вызов будет добавлен в начало существующей цепочки, а не в конец.

# File activesupport/lib/active_support/callbacks.rb, line 642
def set_callback(name, *filter_list, &block)
  type, filters, options = normalize_callback_params(filter_list, block)
  self_chain = get_callbacks name
  mapped = filters.map do |filter|
    Callback.build(self_chain, filter, type, options)
  end

  __update_callbacks(name) do |target, chain|
    options[:prepend] ? chain.prepend(*mapped) : chain.append(*mapped)
    target.set_callbacks name, chain
  end
end
skip_callback(name, *filter_list, &block) Показать исходный код

Пропустить ранее установленный обратный вызов. Как и в случае с set_callback, :if или :unless параметры могут быть переданы для управления временем пропуска обратного вызова.

class Writer < Person
   skip_callback :validate, :before, :check_membership, if: -> { self.age > 18 }
end
# File activesupport/lib/active_support/callbacks.rb, line 662
def skip_callback(name, *filter_list, &block)
  type, filters, options = normalize_callback_params(filter_list, block)

  __update_callbacks(name) do |target, chain|
    filters.each do |filter|
      filter = chain.find {|c| c.matches?(type, filter) }

      if filter && options.any?
        new_filter = filter.merge(chain, options)
        chain.insert(chain.index(filter), new_filter)
      end

      chain.delete(filter)
    end
    target.set_callbacks name, chain
  end
end

Защищённые методы экземпляров

get_callbacks(name) Показать исходный код
# File activesupport/lib/active_support/callbacks.rb, line 778
def get_callbacks(name)
  send "_#{name}_callbacks"
end
set_callbacks(name, callbacks) Показать исходный код
# File activesupport/lib/active_support/callbacks.rb, line 782
def set_callbacks(name, callbacks)
  send "_#{name}_callbacks=", callbacks
end

© 2004–2016 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API