Я хотел бы создать в рельсах функцию обратного вызова, которая выполняется после сохранения модели.
У меня есть эта модель, претензия, которая имеет атрибут «статус», который меняется в зависимости от состояния претензии, возможные значения ожидают, одобрены, одобрены, отклонены
База данных имеет «состояние» со значением по умолчанию «ожидает».
Я хотел бы выполнить определенные задачи после того, как модель будет создана в первый раз или обновлена из одного состояния в другое, в зависимости от того, из какого состояния она изменяется.
Моя идея - иметь функцию в модели:
after_save :check_state
def check_state
# if status changed from nil to pending (created)
do this
# if status changed from pending to approved
performthistask
end
У меня вопрос: как мне проверить предыдущее значение перед изменением модели?
источник
dirty
вызовы работаютafter_save
(как в Rails 2.3, так и в 3.x). Я использовал его несколько раз.after_commit
обратных вызовах, представленных в Rails 3.x. Они обязательно будут работатьafter_save
.after_save
это обратный вызов для состояния междуafter DML
иbefore_commit
. Вы можете завершить всю транзакциюafter_save
, вызвав исключение. Если вы хотите что-то сделать после сохранения, не влияя на текущую операцию, используйтеafter_commit
:-)вы можете использовать это
self.changed
он возвращает массив всех столбцов, которые изменились в этой записи
вы также можете использовать
self.changes
который возвращает хеш столбцов, которые изменились, до и после результатов в виде массивов
источник
self.
них нет необходимости - вы можете просто сказатьchanged
иchanges
.self
когда в самой модели, но вы можете вызвать их для любого объекта с помощьюobject.changed
иobject.changes
. :)Я рекомендую вам взглянуть на один из доступных плагинов конечного автомата:
Любой из них позволит вам устанавливать состояния и переходы между состояниями. Очень полезный и простой способ удовлетворить ваши требования.
источник
Для Rails 5.1+ вы должны использовать метод атрибута активной записи: saved_change_to_attribute?
Итак, ваша модель будет выглядеть так, если вы хотите вызвать какой-либо метод, основанный на изменении значения атрибута:
class Claim < ApplicationRecord after_save :do_this, if: Proc.new { saved_change_to_status?(from: nil, to: 'pending') } after_save :do_that, if: Proc.new { saved_change_to_status?(from: 'pending', to: 'approved') } def do_this .. .. end def do_that .. .. end end
И если вы не хотите проверять изменение значения в обратном вызове, вы можете сделать следующее:
class Claim < ApplicationRecord after_save: :do_this, if: saved_change_to_status? def do_this .. .. end end
источник
Я видел, как этот вопрос поднимался во многих местах, поэтому я написал для него крошечный rubygem, чтобы сделать код немного лучше (и избежать повсюду миллиона операторов if / else): https://github.com/ronna-s / on_change . Надеюсь, это поможет.
источник
Вам будет намного лучше использовать хорошо проверенное решение, такое как гем state_machine .
источник