Eu gostaria de criar uma função de retorno de chamada em trilhos que executa depois que um modelo é salvo.
Eu tenho este modelo, Reivindicação que tem um atributo 'status' que muda dependendo do estado da reivindicação, os valores possíveis são pendentes, endossados, aprovados, rejeitados
O banco de dados tem 'estado' com o valor padrão de 'pendente'.
Gostaria de executar certas tarefas depois que o modelo for criado pela primeira vez ou atualizado de um estado para outro, dependendo de qual estado ele muda.
Minha ideia é ter uma função no modelo:
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
Minha pergunta é como faço para verificar o valor anterior antes da mudança dentro do modelo?
fonte
dirty
chamadas funcionam noafter_save
(tanto no Rails 2.3 quanto no 3.x). Eu usei várias vezes.after_commit
callbacks introduzidos no Rails 3.x. Eles certamente funcionarãoafter_save
.after_save
é um retorno de chamada para um estado entreafter DML
ebefore_commit
. Você pode encerrar a transação inteiraafter_save
lançando uma exceção. Se você quiser fazer algo após salvar sem afetar a operação atual, useafter_commit
:-)você pode usar isso
self.changed
ele retorna um array de todas as colunas que mudaram neste registro
você também pode usar
self.changes
que retorna um hash de colunas que mudaram e antes e depois dos resultados como matrizes
fonte
self.
neles - você pode apenas dizerchanged
echanges
.self
when no próprio modelo, mas pode chamá-los em qualquer objeto comobject.changed
eobject.changes
. :)Eu recomendo que você dê uma olhada em um dos plug-ins de máquina de estado disponíveis:
Qualquer um deles permitirá que você configure estados e transições entre estados. Maneira muito útil e fácil de lidar com seus requisitos.
fonte
Para Rails 5.1+, você deve usar o método de atributo de registro ativo: saved_change_to_attribute?
Portanto, seu modelo ficará assim, se você quiser chamar algum método com base na mudança no valor do atributo:
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
E se você não quiser verificar a mudança de valor no retorno de chamada, você pode fazer o seguinte:
class Claim < ApplicationRecord after_save: :do_this, if: saved_change_to_status? def do_this .. .. end end
fonte
Já vi a questão surgir em muitos lugares, então escrevi um pequeno rubygem para ela, para tornar o código um pouco melhor (e evitar um milhão de instruções if / else em todos os lugares): https://github.com/ronna-s / on_change . Espero que ajude.
fonte
Você ficará muito melhor usando uma solução bem testada, como a gem state_machine .
fonte