Spec-Zone.ru › Ruby on Rails 5.1

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

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

define_callbacks(*names) Показать исходный код
# File activesupport/lib/active_support/callbacks.rb, line 817
        def define_callbacks(*names)
          options = names.extract_options!

          names.each do |name|
            name = name.to_sym

            set_callbacks name, CallbackChain.new(name, options)

            module_eval "              def _run_#{name}_callbacks(&block)
                run_callbacks #{name.inspect}, &block
              end

              def self._#{name}_callbacks
                get_callbacks(#{name.inspect})
              end

              def self._#{name}_callbacks=(value)
                set_callbacks(#{name.inspect}, value)
              end

              def _#{name}_callbacks
                __callbacks[#{name.inspect}]
              end
", __FILE__, __LINE__ + 1
          end
        end

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

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

    define_callbacks :validate, terminator: ->(target, result_lambda) { result_lambda.call == false }
    

    В этом примере, если любой из обратных вызовов before validate вернёт false, любые последующие обратные вызовы before и around не будут выполнены.

    По умолчанию терминатор прерывает цепочку, когда обратный вызов генерирует :abort.

  • :skip_after_callbacks_if_terminated - Определяет, будут ли обратные вызовы after прерываться параметром :terminator. По умолчанию обратные вызовы after выполняются независимо от того, была ли прервана цепочка обратных вызовов или нет. Этот параметр имеет смысл только при указании параметра :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» — «before», а «name» — «save». В этом контексте :kind и :name имеют специальное значение: :kind относится к типу обратного вызова (before/after/around), а :name относится к методу, для которого определяются обратные вызовы.

    Объявление типа

    define_callbacks :save, scope: [:name]
    

    вызовет Audit#save.

Примечания

names , переданный в define_callbacks , не должен заканчиваться на !, ? или =.

Вызов define_callbacks несколько раз с одним и тем же names перезапишет предыдущие обратные вызовы, зарегистрированные с помощью set_callback.

reset_callbacks(name) Показать исходный код
# File activesupport/lib/active_support/callbacks.rb, line 727
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

  set_callbacks(name, callbacks.dup.clear)
end

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

set_callback(name, *filter_list, &block) Показать исходный код
# File activesupport/lib/active_support/callbacks.rb, line 662
        def set_callback(name, *filter_list, &block)
          type, filters, options = normalize_callback_params(filter_list, block)

          if options[:if].is_a?(String) || options[:unless].is_a?(String)
            ActiveSupport::Deprecation.warn("              Passing string to be evaluated in :if and :unless conditional
              options is deprecated and will be removed in Rails 5.2 without
              replacement. Pass a symbol for an instance method, or a lambda,
              proc or block, instead.
".squish)
          end

          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

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

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

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

set_callback :save, :before_method

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

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

Обратные вызовы before и around вызываются в порядке их установки; обратные вызовы after вызываются в обратном порядке.

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

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

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

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

skip_callback(name, *filter_list, &block) Показать исходный код
# File activesupport/lib/active_support/callbacks.rb, line 695
        def skip_callback(name, *filter_list, &block)
          type, filters, options = normalize_callback_params(filter_list, block)

          if options[:if].is_a?(String) || options[:unless].is_a?(String)
            ActiveSupport::Deprecation.warn("              Passing string to :if and :unless conditional options is deprecated
              and will be removed in Rails 5.2 without replacement.
".squish)
          end

          options[:raise] = true unless options.key?(:raise)

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

              if !callback && options[:raise]
                raise ArgumentError, "#{type.to_s.capitalize} #{name} callback #{filter.inspect} has not been defined"
              end

              if callback && (options.key?(:if) || options.key?(:unless))
                new_callback = callback.merge_conditional_options(chain, if_option: options[:if], unless_option: options[:unless])
                chain.insert(chain.index(callback), new_callback)
              end

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

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

class Writer < Person
   skip_callback :validate, :before, :check_membership, if: -> { age > 18 }
end

Будет поднято исключение ArgumentError, если обратный вызов ещё не был установлен (если параметр :raise установлен на false).

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

Spec-Zone.ru

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