Mit Active, ist es eine Möglichkeit, die alten Werte eines Datensatzes zu erhalten während after_update
-
03-07-2019 - |
Frage
Setup ein einfaches Beispiel: ein. Ich habe 1 Tisch (Totals
) bekommt, das die Summe der amount
Spalte jeden Datensatz in einer zweiten Tabelle (Things
) hält
Wenn ein thing.amount
aktualisiert wird, würde Ich mag einfach den Unterschied zwischen dem alten Wert hinzufügen und den neuen Wert total.sum
.
Im Moment self.amount
während before_update
und das Hinzufügen von self.amount
während after_update
ich subtrahieren. Dies stellt viel zu viel Vertrauen in das Update erfolgreich.
Constraint:. Ich will nicht einfach die Summe aller Transaktionen neu zu berechnen
Frage: Ganz einfach, ich möchte den ursprünglichen Wert während eines after_update
Rückruf zuzugreifen. Welche Möglichkeiten haben Sie kommen mit tun?
Update: Ich bin mit Luke Francl Idee geht. Während eines after_update
Rückruf haben Sie noch Zugriff auf die self.attr_was
Werte das ist genau das, was ich wollte. Ich habe auch beschlossen mit einer after_update
Umsetzung zu gehen, weil ich diese Art von Logik im Modell beibehalten möge. Auf diese Weise, egal wie ich mich entscheide, Transaktionen in der Zukunft zu aktualisieren, ich weiß, dass ich die Summe der Transaktionen korrekt bin zu aktualisieren. Vielen Dank an alle für Ihre Implementierung Vorschläge.
Lösung
Ditto, was jeder sagt über Transaktionen.
Das sagte ...
Active wie von Rails 2.1 verfolgt die Attributwerte eines Objekts. Also, wenn Sie ein Attribut total
haben, erhalten Sie eine total_changed?
Verfahren und eine total_was
Methode, die den alten Wert zurückgibt.
Es gibt keine Notwendigkeit, etwas zu Ihrem Modell hinzuzufügen Spur davon zu halten mehr.
Update: Hier ist die Dokumentation für ActiveModel :: Schmutzige wie gewünscht geplant.
Andere Tipps
Einige andere Leute sind zu erwähnen, all dies in einer Transaktion wickeln, aber ich denke, dass für Sie getan hat; Sie müssen nur die Rollback ausgelöst wird, um eine Ausnahme für Fehler in den after_ * Rückrufe zu erhöhen.
Siehe http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
Die gesamte Rückrufkette eines speichern, speichern !, oder Anruf läuft innerhalb einer Transaktion zerstören. Dazu gehören after_ * Haken. Wenn alles gut geht ein COMMIT ausgeführt wird, sobald die Kette abgeschlossen ist.
Wenn ein before_ * Rückruf, um die Aktion ein ROLLBACK abgebrochen ausgegeben. Sie können auch eine ROLLBACK auslösen eine Ausnahme in einem der Rückrufe erhöhen, einschließlich after_ * Haken. Beachten Sie jedoch, dass in diesem Fall der Kunde dessen bewusst sein muss, weil ein gewöhnlicher sparen solche Ausnahme erhöhen statt leise Rückkehr falsch.
Anfügen „_was“ zu Ihrem Attribut geben Sie den vorherigen Wert, bevor die Daten zu speichern.
Diese Methoden schmutzigen Methoden Methoden.
Cheers!
Um alle geänderten Felder zu erhalten, mit ihren alten und neuen Werten, die jeweils:
person = Person.create!(:name => 'Bill')
person.name = 'Bob'
person.save
person.changes # => {"name" => ["Bill", "Bob"]}
Active :: Schmutzige ist ein Modul, das in Activerecord für die Verfolgung errichtet wird Attributänderungen. So können Sie thing.amount_was
verwenden, um den alten Wert zu erhalten.
Fügen Sie diese auf Ihrem Modell:
def amount=(new_value)
@old_amount = read_attribute(:amount)
write_attribute(:amount,new_value)
end
Dann in Ihrem after_update Code verwenden @old_amount.
Zunächst sollten Sie dies in einer Transaktion tun, um sicherzustellen, dass Ihre Daten zusammen geschrieben wird.
Um Ihre Frage zu beantworten, können Sie nur eine Membervariable auf den alten Wert im BEFORE_UPDATE gesetzt, die Sie dann Zugriff im after_update, aber dies nicht eine sehr elegante Lösung.
Idee 1: Wickeln Sie das Update in einer Datenbanktransaktion, so dass, wenn die Aktualisierung Ihrer Summentabelle nicht nicht geändert wird: Active Transaktionen docs
Idee 2: Stash den alten Wert in @old_total während der BEFORE_UPDATE
.