Rusrails колбекі active record

Колбекі Active Record

Це керівництво навчить вас втручатися в життєвий цикл ваших об'єктів Active Record.

Після прочитання цього керівництва ви дізнаєтеся:

  • Про життєвому циклі об'єктів Active Record
  • Як створювати методи колбеков, що відповідають на події в життєвому циклі об'єкта
  • Як створювати спеціальні класи, інкапсулюючих звичайну поведінку для ваших колбеков

1. Життєвий цикл об'єкта

В результаті звичайних операцій додатки на Rails, об'єкти можуть бути створені, оновлені і знищені. Active Record дає можливість втрутитися в цей життєвий цикл об'єкта, таким чином, ви можете контролювати свій додаток і його дані.

Валідації дозволяють вам бути впевненими, що тільки валідниє дані зберігаються у вашій базі даних. Колбекі дозволяють вам перемикати логіку до або після зміни стану об'єкта.

2. Огляд колбеков

Колбекі це методи, які викликаються в певні моменти життєвого циклу об'єкта. З колбекамі можливо написати код, який буде запущений, коли об'єкт Active Record створюється, зберігається, оновлюється, віддаляється, проходить валідацію або завантажується з бази даних.

2.1. Реєстрація колбеков

Для того, щоб використовувати доступні колбекі, їх потрібно зареєструвати. Можна реалізувати колбекі як звичайні методи, а потім використовувати макро-методи класу для їх реєстрації в якості колбеков.

Макро-методи класу також можуть отримувати блок. Їх можна використовувати, якщо код всередині блоку такий короткий, що поміщається в один рядок.

Колбекі також можуть бути зареєстровані на виконання за певних подіях життєвого циклу:

Вважається доброю практикою оголошувати методи колбеков як private. Якщо їх залишити public, вони можуть бути викликані ззовні моделі і порушити принципи інкапсуляції об'єкта.

3. Доступні колбекі

Ось список всіх доступних колбеков Active Record, перерахованих в тому порядку, в якому вони викликаються протягом відповідних операцій:

3.1. створення об'єкта

  • before_validation
  • after_validation
  • before_save
  • around_save
  • before_create
  • around_create
  • after_create
  • after_save
  • after_commit / after_rollback

3.2. оновлення об'єкта

  • before_validation
  • after_validation
  • before_save
  • around_save
  • before_update
  • around_update
  • after_update
  • after_save
  • after_commit / after_rollback

3.3. знищення об'єкта

  • before_destroy
  • around_destroy
  • after_destroy
  • after_commit / after_rollback

after_save запускається і при створенні, і при оновленні, але завжди після більш специфічних колбеков after_create і after_update. не залежно від порядку, в якому запускаються макро-виклики.

Колбек before_destroy повинен бути розміщений перед зв'язками dependent. destroy (або використовувати опцію prepend: true), щоб переконатися, що вони виконуються до того, як записи будуть видалені з допомогою dependent. destroy.

3.4. after_initialize і after_find

Колбек after_initialize викликається всякий раз, коли виникає екземпляр об'єкта Active Record, або безпосередньо при використанні new. або коли запис завантажується з бази даних. Він може бути корисний, щоб уникнути необхідності безпосередньо перевизначати метод Active Record initialize.

Колбек after_find буде викликаний щоразу, коли Active Record завантажує запис з бази даних. after_find викликається перед after_initialize. якщо вони обидва визначені.

У колбеков after_initialize і after_find немає пари before_ *. але вони можуть бути зареєстровані подібно іншим колбекам Active Record.

3.5. after_touch

Колбек after_touch буде викликаний, коли на об'єкті Active Record викликаний touch.

Він може бути використаний спільно з belongs_to:

4. Запуск колбеков

Наступні методи запускають колбекі:

Додатково, колбек after_find запускається наступними пошуковими методами:

Колбек after_initialize запускається кожного разу, коли инициализируется новий об'єкт класу.

Методи find_by_ * і find_by_ *! це динамічні методи пошуку, які генеруються автоматично для кожного атрибута. Вивчіть докладніше їх в розділі Динамічний пошук

5. Пропуск колбеков

Подібно валідації, також можливо пропустити колбекі, використовуючи такі методи.

  • decrement
  • decrement_counter
  • delete
  • delete_all
  • increment
  • increment_counter
  • toggle
  • touch
  • update_column
  • update_columns
  • update_all
  • update_counters

Однак, ці методи потрібно використовувати обережно, оскільки важливі бізнес-правила і логіка додатки можуть міститися в колбеках. Пропуск їх без розуміння можливих наслідків може привести до невалідним даними.

6. Переривання виконання

Як тільки ви зареєстрували нові колбекі в своїх моделях, вони будуть поставлені в чергу на виконання. Ця чергу включає всі валідації вашої моделі, зареєстровані колбекі і операції з базою даних для виконання.

Весь ланцюжок колбеков упаковується в операцію. Якщо будь-який колбек викликає виняток, виконувана ланцюжок переривається і запускається ROLLBACK. Щоб навмисно зупинити ланцюжок, використовуйте:

Виклик довільного виключення може перервати код, який передбачає, що save тощо не будуть провалені подібним чином. Виняток ActiveRecord :: Rollback трохи точніше повідомляє Active Record, що відбувається відкат. Він підхоплюється зсередини, але не перевизивает виняток.

Будь-яке виключення, крім ActiveRecord :: Rollback або ActiveRecord :: RecordInvalid. буде перевизвано Rails після того, як перерветься ланцюжок колбеков. Виклик виключення, відмінного від ActiveRecord :: Rollback або ActiveRecord :: RecordInvalid. може зламати код, який не очікує, що методи, такі як save і update_attributes (які зазвичай намагаються повернути true або false) викличуть виняток.

7. Колбекі для відносин

Колбекі працюють з відносинами між моделями, і навіть можуть бути визначені ними. Уявімо приклад, де користувач має багато статей. Статті користувача повинні бути знищені, якщо знищується користувач. Давайте додамо колбек after_destroy в модель User через її відносини з моделлю Article.

8. Умовні колбекі

Як і в валідації, можливо зробити виклик методу колбека умовним в залежності від заданого предиката. Це здійснюється при використанні опцій: if і: unless. які можуть приймати символ, Proc або масив. Опцію: if слід використовувати для визначення, за яких умов колбек повинен бути викликаний. Якщо ви хочете визначити умови, при яких колбек не повинен бути викликаний, використовуйте опцію: unless.

8.1. Використання: if і: unless з символом

Опції: if і: unless можна пов'язати з символом, відповідним імені методу предиката, який буде викликаний безпосередньо перед викликом колбека. При використанні опції: if. колбек не буде виконано, якщо метод предиката поверне false; при використанні опції: unless. колбек не буде виконано, якщо метод предиката поверне true. Це найпоширеніший варіант. При використанні такої форми реєстрації, також можливо зареєструвати декілька різних предикатів, які будуть викликані для перевірки, чи повинен запуститися колбек.

8.2. Використання: if і: unless з Proc

Нарешті, можна зв'язати: if і: unless з об'єктом Proc. Цей варіант найбільше підходить при написанні коротких методів, зазвичай однорядкових.

8.3. Складові умови для колбеков

9. Класи колбеков

Іноді написання вами методи колбеков досить корисні для повторного використання в інших моделях. Active Record уможливлює створювати класи, що включають методи колбека, так, що стає дуже легко використовувати їх повторно.

Ось приклад, де створюється клас з колбеком after_destroy для моделі PictureFile:

Якщо метод колбека оголошується таким чином, немає необхідності створювати екземпляр об'єкта PictureFileCallbacks.

Усередині свого колбек-класу можна створити скільки завгодно колбеков.

10. Транзакційні колбекі

Є два додаткових колбека, які включаються по завершенню транзакції бази даних: after_commit і after_rollback. Ці колбекі дуже схожі на колбек after_save. за винятком того, що вони не запускаються поки зміни в базі даних не будуть підтверджені або звернені. Вони найбільш корисні, коли вашим моделям Active Record необхідно взаємодіяти з зовнішніми системами, які не є частиною транзакції бази даних.

Розглянемо, наприклад, попередній приклад, де моделі PictureFile необхідно видалити файл після того, як запис знищена. Якщо що-небудь викличе виключення після того, як був викликаний колбек after_destroy. і транзакція відкочується, файл буде видалений і модель залишиться в суперечливому стані. Наприклад, припустимо, що picture_file_2 в наступному коді не правильна, і метод save! викличе помилку.

Використовуючи колбек after_commit. можна врахувати цей випадок.

Опція: on визначає, коли буде запущений колбек. Якщо не надати опцію: on. колбек буде запущений для кожного екшна.

Так як прийнято використовувати колбек after_commit тільки при створенні, оновленні або видаленні, є псевдоніми для цих операцій:

  • after_create_commit
  • after_update_commit
  • after_destroy_commit

Колбекі after_commit і after_rollback викликаються для всіх створених, оновлених або віддалених моделей всередині блоку транзакції. Однак, якщо будь-яка виняток зголоситься в одному з цих колбеков, це виняток спливе, і будь-які залишилися методи after_commit або after_rollback не будуть виконані. По суті, якщо код вашого колбека може викликати виключення, потрібно для нього викликати rescue, і обробити його в колбеке, щоб дозволити запуститися іншим колбекам.

При одночасному використанні after_create_commit і after_update_commit в одній і тій же моделі спрацює тільки колбек, певний останнім, перевизначивши всі інші.

Щоб зареєструвати колбекі як для create, так і для update екшнів, використовуйте after_commit.