Ich habe ein besonders komplexes Modell mit definierten Validierungen und Rückrufen. Die geschäftlichen Anforderungen erfordern jetzt ein bestimmtes Szenario, in dem das Hinzufügen eines neuen Datensatzes das Überspringen der Validierungen und Rückrufe erfordert. Was ist der beste Weg, dies zu tun?
ruby-on-rails
ruby-on-rails-3
activerecord
Johnny Klassy
quelle
quelle
set_callback(:create)
? Ich hatte den Eindruck, dass esskip_callback
deaktiviert wird, bis es wieder aktiviert wird.Verwenden Sie ActiveRecord :: Persistence # update_column wie folgt :
quelle
update_attribute
, nicht nachupdate_column
. Wenn Sie sich die Dokumentation ansehenupdate_column
, entspricht diesupdate_columns
einer einzelnen Spalte. In den Dokumenten wirdupdate_columns
eindeutig angegeben, dass Validierungen und Rückrufe übersprungen werden.Wenn das Ziel darin besteht, einfach einen Datensatz ohne Rückrufe oder Überprüfungen einzufügen oder zu aktualisieren, 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 Beendigungscode zu fummeln, kann dies der Fall sein Es ist möglich, ein "Schattenobjekt" zu verwenden, das auf Ihre vorhandene DB-Tabelle verweist. Wie so:
class ImportedUser < ActiveRecord::Base # To import users with no validations or callbacks self.table_name = 'users' end
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. Denken Sie daran, Ihre neue Klasse zum Einfügen des Objekts zu verwenden, z.
quelle
Meine Einstellung war wie folgt (Hinweis: Dadurch werden Rückrufe beim Erstellen, Aktualisieren, Löschen und andere deaktiviert, die Sie zum Array hinzufügen müssen).
begin [:create, :save].each{|a| self.class.skip_callback(a) } # We disable callbacks on save and create # create new record here without callbacks, tou can also disable validations with # .save(:validate => false) ensure [:create, :save].each{|a| self.class.set_callback(a) } # and we ensure that callbacks are restored end
quelle
Ich würde empfehlen, den skip_callback-Ansatz NICHT zu verwenden, da er nicht threadsicher ist. Das hinterhältige Juwel ist jedoch, dass es nur gerade SQL läuft. Beachten Sie, dass dies keine Validierungen auslöst, sodass Sie sie selbst aufrufen müssen (z. B. my_model.valid?).
Hier sind einige Beispiele aus ihren Dokumenten:
# Update. Returns true on success, false otherwise. existing_record.sneaky_save # Insert. Returns true on success, false otherwise. Model.new.sneaky_save # Raise exception on failure. record.sneaky_save!
quelle
Wie wäre es, wenn Sie Ihrem Modell eine Methode hinzufügen, mit der Sie die Rückrufe überspringen können?
class Foo < ActiveRecord::Base after_save :do_stuff def super_secret_create(attrs) self.skip_callback(:create) self.update_attributes(attrs) self.save(:validate => false) self.set_callback(:create) end end
Wenn Sie am Ende so etwas verwenden, würde ich empfehlen, self in der Methode anstelle des Modellnamens zu verwenden, um die Konnotation des Namens zu vermeiden.
Ich bin auch auf einen Kern von Sven Fuchs gestoßen, der gut aussieht, er ist hier
quelle
skip_callback
als Klassenmethode angezeigt, währendupdate_attributes
es sich um eine Instanzmethode handelt. Haben Sie das beabsichtigt? Hmm, ich verstehe es nicht, das API-Dokument sagt, esskip_callback
sei eine Instanzmethode, aber es ist nicht so in der Rails-Konsole, seltsam.Ich habe ein einfaches Juwel geschrieben, um Validierungen adhoc zu überspringen, aber es könnte wahrscheinlich aktualisiert werden, um auch das Überspringen von Rückrufen einzuschließen.
https://github.com/npearson72/validation_skipper
Sie können das
can_skip_validation_for
in den Edelstein nehmen und Funktionen hinzufügen, um auch Rückrufe zu überspringen. Vielleicht die Methode aufrufencan_skip_validation_and_callbacks_for
Alles andere würde gleich funktionieren. Wenn Sie dabei Hilfe benötigen, lassen Sie es mich wissen.
quelle
Dieser Hack hat endlich bei mir funktioniert (neu definierte
_notify_comment_observer_for_after_create
Methode für das Objekt):if no_after_create_callback def object._notify_comment_observer_for_after_create; nil; end end
quelle
Keines davon funktioniert, wenn Ihre Validierungen in die Datenbank selbst geschrieben werden.
+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+ | status | enum('Big','Small','Ugly','Stupid','Apologetic') | NO | | Stupid | |
quelle