Коллбэки Active Record

Введение

Коллбэки (функции обратного вызова) - это распространенный способ исполнять пользовательский код в определенные моменты жизненного цикла объекта Active Record, например прямо перед его созданием, после его сохранения или после его уничтожения. Это может быть очень полезным, если вам необходимо выполнить некие действия, когда объект проходит одну из стадий своего жизненного цикла, вроде перевода всех символов из e-mail пользователя в нижний регистр при создании его аккаунта. Коллбэки - это способ сказать что-то вроде "Эй, Active Record, когда закончишь создание нового объекта пользователя, сообщи мне, чтоб я мог запустить этот метод перед тем, как произойдет что-нибудь еще."

Это краткое описание этой полезной темы. Чтение RusRails (или Rails Guides) хорошо освещает эту тему, так что этот урок будет действительно лаконичным.

Пункты для размышления

Просмотрите вопросы и проверьте, знаете ли на них ответы. Проверьте себя снова после выполнения задания.

  • Для чего используются коллбэки?
  • Назовите основные стадии жизненного цикла объекта Active Record.
  • Как создать "around"-коллбэк?
  • Как указать в частности для какого действия должен запускаться коллбэк?

Жизненный цикл объекта Active Record

Коллбэки предоставляют хуки (перехватчики) в определенных моментах (до (before), после (after) и иногда "around") жизненного цикла объекта. Список стадий жизненного цикла:

  • Инициализация - когда объект впервые сконструирован (создан в памяти) ИЛИ в любой момент перезагрузки из базы данных в память (что значит каждый раз при получении его с помощью запроса).
  • Валидация - когда Rails проверяет корректность вашего объекта (на основе описанных вами валидаций). Это может происходить, когда вы пытаетесь сохранить объект, или когда вы вручную вызываете метод #valid?.
  • Сохранение - реальный процесс сохранения уже сконструированного объекта в базу данных. Это происходит каждый раз при сохранении объекта, а не только в первый раз при его создании.
  • Создание - создание и сохранение нового объекта.
  • Обновление - обновление существующего объекта.
  • Успешный поиск - когда вы производили поиск объекта. Часто вызывается Rails при фоновой(неявной) работе с объектами (например, при использовании метода ::first - явного поиска не происходит, но коллбэк будет вызван).

Как правило, у вас будет выбор из 3 коллбэков. Не все шаги жизненного цикла объектов поддерживают полный набор коллбэков, но основными являются (на примере create):

  1. before_create - запускает метод до указанного действия
  2. after_create - запускает метод после указанного действия
  3. around_create - немного сложнее. В этом случае, вы пишете метод, который с помощью yield в определенный момент передает управление изначальному действию. Таким образом, вы можете выполнять код и до, и после действия, и ВЫ решаете в какой момент будет выполнено изначальное действие. Не особо часто используется.

Использование коллбэков

Для использования коллбэка вам понадобится "зарегистрировать" его вверху вашей модели, используя соответствующий метод (например, before_create). Вы передаете методу либо символ, соответствующий имени метода, либо вы можете описать коллбэк с помощью блока прямо на месте. Rails привяжет этот метод и вызовет его в соответствующий момент. Например:

    # app/models/user.rb
    class User < ActiveRecord::Base
      before_create do |user|
        puts "about to create #{user.name}"
      end
      after_create :just_created

      protected
      def just_created
        puts "just created a user"
      end
    end

Указание характеристик коллбэков

Коллбэки предоставляют вам несколько вариантов для сужения списка ситуаций или точного выбора, при которых коллбэки будут запускаться. Если вы просто хотите запустить коллбэк, когда определенное действие контроллера его вызывает, используйте опцию :on, которая принимает символ или массив символов, например before_create :run_code, on: [:create, :update].

Вы также можете использовать условные логические опции :if и :unless для проверки методом перед запуском коллбэка, например:

    ...
    before_create :run_code, unless: :method_is_true

    protected
    def method_is_true
      true
    end
    ...

Коллбэки транзакций

Иногда вашему Rails-приложению требуется взаимодействие с внешним приложением (которое само по себе не совершенно) как часть процесса сохранения. В другой ситуации ваш процесс сохранения может включать нетривиальную логику работы с несколькими объектами, и если какая-то ее часть не выполнилась, все объекты нужно откатить назад. Обычно, в этих ситуациях операция сохранения в базу данных оборачивается в "транзакцию", что означает необходимость корректности работы каждого шага алгоритма, либо все эти шаги будут считаться проваленными, а действия откатятся назад.
Операции применения (commit) транзакции и ее потенциального отката (rollback) при неудаче являются событиями жизненного цикла, и вы можете повесить на них коллбэки, например after_commit и before_rollback. Это нечасто применяется, так что считайте это очередной информацией вида "просто запомните, что так можно делать".

Задание

  1. Прочитайте раздел Колбэки Active Record.
  2. Прочитайте этот пост Samuel Mullen по советам использования коллбэков.

Заключение

Коллбэки полезны и многие, вроде :after_create и :before_destroy, довольно часто используются. В них нет ничего мудреного, это просто удобная концепция.

Дополнительные ресурсы

Этот раздел содержит полезные ссылки на дополнительные материалы. Они не обязательны, так что расценивайте их как нечто полезное, если вы хотите поглубже погрузиться в тему

  • Страница WikiBooks по коллбэкам

Поделиться уроком: