Ich habe einige Modelle mit After_Save-Rückrufen. Normalerweise ist das in Ordnung, aber in einigen Situationen, z. B. beim Erstellen von Entwicklungsdaten, möchte ich die Modelle speichern, ohne dass die Rückrufe ausgeführt werden. Gibt es eine einfache Möglichkeit, das zu tun? So etwas wie ...
Person#save( :run_callbacks => false )
oder
Person#save_without_callbacks
Ich habe in den Rails-Dokumenten nachgesehen und nichts gefunden. Nach meiner Erfahrung erzählen die Rails-Dokumente jedoch nicht immer die ganze Geschichte.
AKTUALISIEREN
Ich habe einen Blog-Beitrag gefunden , in dem erklärt wird, wie Sie Rückrufe aus einem Modell wie diesem entfernen können:
Foo.after_save.clear
Ich konnte nicht finden, wo diese Methode dokumentiert ist, aber sie scheint zu funktionieren.
Foo.after_save.clear
Rückrufe nicht für das gesamte Modell entfernen? Und wie schlagen Sie dann vor, sie wiederherzustellen?Antworten:
Diese Lösung ist nur Rails 2.
Ich habe das gerade untersucht und denke, ich habe eine Lösung. Es gibt zwei private ActiveRecord-Methoden, die Sie verwenden können:
Sie müssen send verwenden, um diese Methoden aufzurufen. Beispiele:
Dies ist definitiv etwas, das Sie wirklich nur in der Konsole oder bei zufälligen Tests verwenden möchten. Hoffe das hilft!
quelle
Verwenden Sie
update_column
(Rails> = v3.1) oderupdate_columns
(Rails> = 4.0), um Rückrufe und Validierungen zu überspringen. Auch mit diesen Methodenupdated_at
wird nicht aktualisiert.http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column
# 2: Rückrufe überspringen, die auch beim Erstellen eines Objekts funktionieren
quelle
:create_without_callbacks
:( Wie kann ich etwas Ähnliches ausführen? (Arbeitete in Rails2, entfernt in Rails3).@person
handelt sich irgendwo um eine Variable in einem Controller, bedeutet diese Lösung, dass Personen, die Ihre Modellklasse lesen, die Rückrufe nicht verstehen können. Sie werden sehenafter_create :something_cool
und denken "großartig, etwas Cooles passiert nach dem Erstellen!". Um Ihre Modellklasse tatsächlich zu verstehen, müssen sie alle Ihre Controller durchsuchen und nach all den kleinen Stellen suchen, an denen Sie sich entschieden haben, Logik einzufügen. Ich mag es nicht> o <;;skip_callback ..., if: :skip_some_callbacks
durchafter_create ..., unless: :skip_some_callbacks
, um dies ordnungsgemäß mit after_create auszuführen.Aktualisiert:
@ Vikrant Chaudharys Lösung scheint besser zu sein:
Meine ursprüngliche Antwort:
siehe diesen Link: Wie überspringe ActiveRecord-Rückrufe?
in Rails3,
Angenommen, wir haben eine Klassendefinition:
Ansatz1:
Ansatz 2: Wenn Sie sie in Ihren rspec-Dateien oder was auch immer überspringen möchten, versuchen Sie Folgendes:
HINWEIS: Wenn Sie sich nicht in einer rspec-Umgebung befinden, sollten Sie die Rückrufe zurücksetzen:
funktioniert gut für mich auf Schienen 3.0.5
quelle
Schienen 3:
quelle
reset_callbacks
ist nicht:after_save
, sondern:save
. apidock.com/rails/v3.0.9/ActiveSupport/Callbacks/ClassMethods/…Wenn das Ziel darin besteht, einfach einen Datensatz ohne Rückrufe oder Validierungen einzufügen, und Sie dies tun möchten, ohne auf zusätzliche Edelsteine zurückzugreifen, bedingte Überprüfungen hinzuzufügen, RAW SQL zu verwenden oder in irgendeiner Weise mit Ihrem vorhandenen Code zu fummeln, sollten Sie die Verwendung eines "Schattens" in Betracht ziehen Objekt "zeigt auf Ihre vorhandene DB-Tabelle. Wie so:
Dies funktioniert mit jeder Version von Rails, ist threadsicher und eliminiert alle Validierungen und Rückrufe vollständig, ohne Änderungen an Ihrem vorhandenen Code vorzunehmen. Sie können diese Klassendeklaration einfach direkt vor Ihrem eigentlichen Import einwerfen, und Sie sollten bereit sein, loszulegen. Denken Sie daran, Ihre neue Klasse zum Einfügen des Objekts zu verwenden, z.
quelle
Sie könnten so etwas in Ihrem Personenmodell ausprobieren:
EDIT: after_save ist kein Symbol, aber das ist mindestens das 1000. Mal, dass ich versucht habe, es zu einem zu machen.
quelle
send
. KOODOSSie können verwenden
update_columns
:quelle
Die einzige Möglichkeit, alle after_save-Rückrufe zu verhindern, besteht darin, dass der erste false zurückgibt.
Vielleicht könnten Sie etwas versuchen wie (ungetestet):
quelle
Eine Möglichkeit, dies in Rails 2.3 zu handhaben (da update_without_callbacks weg ist usw.), besteht darin, update_all zu verwenden. Dies ist eine der Methoden, mit denen Rückrufe gemäß Abschnitt 12 des Rails-Handbuchs zu Validierungen und Rückrufen übersprungen werden .
Beachten Sie außerdem, dass Sie, wenn Sie in Ihrem after_-Rückruf etwas tun, das eine Berechnung basierend auf vielen Zuordnungen durchführt (dh eine has_many-Zuordnung, in der Sie auch_nested_attributes_for akzeptieren), die Zuordnung neu laden müssen, falls dies Teil des Speichervorgangs ist wurde eines seiner Mitglieder gelöscht.
quelle
https://gist.github.com/576546
Speichern Sie diesen Affen-Patch einfach in config / initializers / skip_callbacks.rb
dann
Project.skip_callbacks { @project.save }
oder so ähnlich.
Alle Gutschrift an den Autor
quelle
Am meisten
up-voted
Antworten scheinen in einigen Fällen verwirrend.Sie können nur eine einfache
if
Überprüfung verwenden, wenn Sie einen Rückruf wie folgt überspringen möchten:quelle
Eine Lösung, die für alle Versionen von Rails ohne Verwendung eines Gems oder Plugins funktionieren sollte, besteht einfach darin, Update-Anweisungen direkt auszugeben. z.B
Dies kann eine Option sein (oder auch nicht), je nachdem, wie komplex Ihr Update ist. Dies funktioniert gut, um beispielsweise Flags in einem Datensatz innerhalb eines after_save-Rückrufs zu aktualisieren (ohne den Rückruf erneut auszulösen).
quelle
#{...}
.quelle
Keiner dieser Punkte für ein
without_callbacks
Plugin, das genau das tut, was Sie brauchen ...http://github.com/cjbottaro/without_callbacks funktioniert mit Rails 2.x.
quelle
Ich habe ein Plugin geschrieben, das update_without_callbacks in Rails 3 implementiert:
http://github.com/dball/skip_activerecord_callbacks
Ich denke, die richtige Lösung besteht darin, Ihre Modelle neu zu schreiben, um Rückrufe zu vermeiden. Wenn dies jedoch kurzfristig unpraktisch ist, kann dieses Plugin hilfreich sein.
quelle
Wenn Sie Rails 2 verwenden. Sie können die SQL-Abfrage zum Aktualisieren Ihrer Spalte verwenden, ohne Rückrufe und Überprüfungen auszuführen.
Ich denke, es sollte in allen Rails-Versionen funktionieren.
quelle
Wenn ich die volle Kontrolle über den Rückruf benötige, erstelle ich ein weiteres Attribut, das als Switch verwendet wird. Einfach und effektiv:
Modell:
Prüfung:
quelle
Zum Erstellen von Testdaten in Rails verwenden Sie diesen Hack:
https://coderwall.com/p/y3yp2q/edit
quelle
Sie können Sneaky-Save Gem verwenden: https://rubygems.org/gems/sneaky-save .
Beachten Sie, dass dies beim Speichern von Assoziationen ohne Validierungen nicht hilfreich sein kann. Es wird der Fehler 'created_at darf nicht null sein' ausgelöst, da die SQL-Abfrage im Gegensatz zu einem Modell direkt eingefügt wird. Um dies zu implementieren, müssen wir alle automatisch generierten Spalten von db aktualisieren.
quelle
Ich brauchte eine Lösung für Rails 4, also habe ich mir Folgendes ausgedacht:
App / Modelle / Bedenken / save_without_callbacks.rb
in jedem Modell:
dann kannst du:
oder
quelle
Warum möchten Sie dies in der Entwicklung tun können? Dies bedeutet sicherlich, dass Sie Ihre Anwendung mit ungültigen Daten erstellen und sich als solche seltsam verhalten und nicht so, wie Sie es in der Produktion erwarten.
Wenn Sie Ihre Entwickler-Datenbank mit Daten füllen möchten, besteht ein besserer Ansatz darin, eine Rechenaufgabe zu erstellen, bei der mithilfe des Fälscher-Edelsteins gültige Daten erstellt und in die Datenbank importiert werden, um so viele oder wenige Datensätze zu erstellen, wie Sie möchten Ich denke, Update_without_callbacks und create_without_callbacks funktionieren einwandfrei. Wenn Sie jedoch versuchen, die Schienen nach Ihrem Willen zu biegen, fragen Sie sich, ob Sie einen guten Grund haben und ob das, was Sie tun, wirklich eine gute Idee ist.
quelle
Eine Möglichkeit besteht darin, ein separates Modell für solche Manipulationen unter Verwendung derselben Tabelle zu haben:
(Der gleiche Ansatz könnte das Umgehen von Validierungen erleichtern.)
Stephan
quelle
Eine andere Möglichkeit wäre die Verwendung von Validierungs-Hooks anstelle von Rückrufen. Beispielsweise:
Auf diese Weise können Sie das do_something standardmäßig erhalten, aber Sie können es leicht überschreiben mit:
quelle
Etwas, das mit allen Versionen von
ActiveRecord
ohne funktionieren sollte, abhängig von Optionen oder Aktivaufzeichnungsmethoden, die möglicherweise vorhanden sind oder nicht.TLDR: Verwenden Sie ein "anderes Aktivaufzeichnungsmodell" für dieselbe Tabelle
quelle
Verwenden Sie für benutzerdefinierte Rückrufe ein
attr_accessor
und einunless
im Rückruf.Definieren Sie Ihr Modell wie folgt:
Wenn Sie den Datensatz speichern müssen, ohne die von
after_save
Ihnen definierten Rückrufe auszuführen, setzen Sie dasskip_after_save_callbacks
virtuelle Attribut auftrue
.quelle
Nicht der sauberste Weg, aber Sie könnten den Rückrufcode in einen Zustand einschließen, der die Rails-Umgebung überprüft.
quelle