Sie können eine Transaktion in einem Controller verwenden, wenn Sie dies wirklich möchten. Wie Sie bemerkt haben, ist es eine schlechte Übung, aber wenn Sie es tun wollen, rufen Sie einfach Product.transaction do
statt transaction do
. transaction
ist eine Klassenmethode unter ActiveRecord::Base
, daher müssen Sie sie in einer ActiveRecord-abgeleiteten Klasse aufrufen. Jede Modellklasse in Ihrer Anwendung reicht aus (Vorsicht, wenn Sie sich mit verschiedenen Datenbanken für verschiedene Modelle verbinden, das ist vielleicht nicht wahr ... aber das tun Sie wahrscheinlich nicht).
Der Grund, warum dies eine schlechte Praxis ist, ist, dass es Probleme nicht ordnungsgemäß nach dem MVC-Paradigma trennt. Ihr Controller sollte sich nicht so sehr mit der Implementierung Ihrer Datenpersistenz befassen. Ein besserer Ansatz wäre es, eine Methode zu hinzuzufügen. Vielleicht so etwas wie folgt aus:
def save_and_update_create_time
transaction do
if save
client.update_attribute(:product_create, Time.now)
end
end
end
Dann statt product.save
in Ihrem Controller zu rufen, rufen product.save_and_update_client_create_time
. Möglicherweise müssen Sie auch client
an diese Methode übergeben. Es ist unklar, aus welchem Code client
stammt. Wenn es ein Attribut auf product
ist, sollte die obige Methode funktionieren.
Es gibt bessere, mehr Railsy Möglichkeiten, dies auch zu tun, vor allem, wenn ein product
über seine client
weiß, ohne irgendwelche Controller-Daten. Dann können Sie einfach einen after_save
Rückruf verwenden, wie folgt aus (in den Product
Klasse):
after_save :update_client
private
def update_client(product)
product.client.update_attribute(:product_create, Time.now)
end
dann jedes Mal, wenn ein Product
gespeichert wird, wird das Feld auf dem zugehörigen Client aktualisiert werden. Sie müssen möglicherweise einen Code einführen, um zuerst nach der Existenz eines client
zu suchen.
Der Vorteil der Verwendung von Rückrufen besteht neben saubererem Code darin, dass die gesamte Rückrufkette in einer einzigen Transaktion zusammen mit dem Speichervorgang ausgeführt wird. Sie müssen die Transaktion nicht manuell erstellen. Sie können mehr über Rückrufe in der Rails documentation lesen.
Vielen Dank Jim, du hilfst mir wirklich bei deiner Erklärung! – user1364684
Wenn transaktionale Logik in ein Modell eingefügt wird, wären Transaktionen dann nicht auf ein Modell beschränkt, um die separate Problemregel nicht zu trennen? In der Regel besteht eine hohe Wahrscheinlichkeit, dass sich Transaktionen über mehrere Modelle erstrecken, die auf DB-Ebene nicht notwendigerweise miteinander in Beziehung stehen. – xSNRG
Ja, ich hatte eine Veränderung des Herzens in diesem speziellen Aspekt meines Kommentars. Ich mag die Idee, es aus dem Controller herauszuhalten, aber Multi-Modell-Interaktionen sollten irgendwo verpackt werden.Vielleicht eine andere Klasse, aber in manchen Situationen ist der Controller vielleicht der richtige Ort. –