Einrichtung anhand eines einfachen Beispiels: Ich habe 1 Tabelle ( Totals
), die die Summe der amount
Spalten jedes Datensatzes in einer zweiten Tabelle ( Things
) enthält.
Wenn a thing.amount
aktualisiert wird, möchte ich einfach die Differenz zwischen dem alten und dem neuen Wert hinzufügen total.sum
.
Im Moment subtrahiere ich self.amount
während before_update
und addiere self.amount
während after_update
. Dies setzt viel zu viel Vertrauen in das erfolgreiche Update.
Einschränkung: Ich möchte nicht einfach die Summe aller Transaktionen neu berechnen.
Frage: Ganz einfach, ich möchte während eines after_update
Rückrufs auf den ursprünglichen Wert zugreifen . Wie haben Sie sich das ausgedacht?
Update: Ich gehe mit Luke Francls Idee. Während eines after_update
Rückrufs haben Sie immer noch Zugriff auf die self.attr_was
Werte, genau das, was ich wollte. Ich habe mich auch für eine after_update
Implementierung entschieden, weil ich diese Art von Logik im Modell behalten möchte. Unabhängig davon, wie ich mich entscheide, Transaktionen in Zukunft zu aktualisieren, weiß ich auf diese Weise, dass ich die Summe der Transaktionen korrekt aktualisiere. Vielen Dank an alle für Ihre Implementierungsvorschläge.
Einige andere Leute erwähnen, dass sie all dies in eine Transaktion einwickeln sollen, aber ich denke, das ist für Sie erledigt. Sie müssen nur den Rollback auslösen, indem Sie eine Ausnahme für Fehler in den after_ * -Rückrufen auslösen.
Siehe http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
quelle
Wenn Sie "_was" an Ihr Attribut anhängen, erhalten Sie den vorherigen Wert, bevor Sie die Daten speichern.
Diese Methoden werden als Dirty-Methods- Methoden bezeichnet.
Prost!
quelle
So erhalten Sie alle geänderten Felder mit ihren alten bzw. neuen Werten:
person = Person.create!(:name => 'Bill') person.name = 'Bob' person.save person.changes # => {"name" => ["Bill", "Bob"]}
quelle
person.previous_changes
stattperson.changes
ActiveRecord :: Dirty ist ein in ActiveRecord integriertes Modul zum Verfolgen von Attributänderungen. Sie können also verwenden
thing.amount_was
, um den alten Wert zu erhalten.quelle
Fügen Sie dies Ihrem Modell hinzu:
def amount=(new_value) @old_amount = read_attribute(:amount) write_attribute(:amount,new_value) end
Verwenden Sie dann @old_amount in Ihrem after_update-Code.
quelle
Erstens sollten Sie dies in einer Transaktion tun, um sicherzustellen, dass Ihre Daten zusammen geschrieben werden.
Um Ihre Frage zu beantworten, können Sie einfach eine Mitgliedsvariable auf den alten Wert im before_update setzen, auf den Sie dann im after_update zugreifen können. Dies ist jedoch keine sehr elegante Lösung.
quelle
Idee 1: Schließen Sie das Update in eine Datenbanktransaktion ein, damit Ihre Totals-Tabelle nicht geändert wird, wenn das Update fehlschlägt: ActiveRecord Transactions-Dokumente
Idee 2: Verstecken Sie den alten Wert in @old_total während des before_update.
quelle