Я хотел бы создать функцию обратного вызова в рельсах, которая выполняется после сохранения модели.
У меня есть эта модель, утверждающая, что имеет атрибут "статус", который изменяется в зависимости от состояния претензии, возможные значения ожидаются, одобряются, утверждаются, отклоняются
В базе данных есть "состояние" со значением по умолчанию "ожидающий".
Я хочу выполнить определенные задачи после того, как модель будет создана в первый раз или обновлена из одного состояния в другое, в зависимости от того, из какого состояния оно изменяется.
Моя идея - иметь функцию в модели:
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
Мой вопрос: как проверить предыдущее значение перед изменением в модели?
Ответ 1
Вы должны посмотреть модуль ActiveModel:: Dirty:
Вы должны выполнить следующие действия над своей моделью претензии:
claim.status_changed? # returns true if 'status' attribute has changed
claim.status_was # returns the previous value of 'status' attribute
claim.status_change # => ['old value', 'new value'] returns the old and
# new value for 'status' attribute
claim.name = 'Bob'
claim.changed # => ["name"]
claim.changes # => {"name" => ["Bill", "Bob"]}
О! радости рельсов!
Ответ 2
вы можете использовать этот
self.changed
он возвращает массив всех столбцов, которые были изменены в этой записи
вы также можете использовать
self.changes
который возвращает хеш столбцов, которые были изменены, и до и после результатов в виде массивов
Ответ 3
Я рекомендую вам посмотреть один из доступных плагинов конечного автомата:
Любой из них позволит вам устанавливать состояния и переходы между состояниями. Очень полезный и простой способ удовлетворить ваши требования.
Ответ 4
Я видел, как вопрос поднимался во многих местах, поэтому я написал для него крошечный рубигем, чтобы сделать код немного приятнее (и везде избегайте утверждений if/else): https://github.com/ronna-s/on_change.
Надеюсь, что это поможет.
Ответ 5
Вам будет намного лучше использовать хорошо протестированное решение, например state_machine gem.
Ответ 6
Для Rails 5. 1+, вы должны использовать метод атрибута активной записи.
saved_change_to_attribute? (attr_name, ** options) '
Изменился ли этот атрибут при последнем сохранении? Этот метод может быть вызван как saved_change_to_name?
вместо saved_change_to_attribute?("name")
. Ведет себя аналогично attribute_changed?
, Этот метод полезен после обратных вызовов, чтобы определить, изменил ли вызов сохранения определенный атрибут.
Опции
from
При передаче этот метод будет возвращать false, если исходное значение не равно заданному параметру
to
При передаче, этот метод возвращает ложь, если значение не было изменено в заданное значение
Таким образом, ваша модель будет выглядеть следующим образом, если вы хотите вызвать какой-либо метод, основанный на изменении значения атрибута:
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