Ich habe ein besonders komplexes Modell mit definierten Validierungen und Rückrufen. Das Unternehmen benötigt nun 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?
Das funktioniert in Rails 3:
Model.skip_callback(:create)
model.save(:validate => false)
Model.set_callback(:create)
( API-Dokumente und verwandte Frage )
Verwenden Sie ActiveRecord :: Persistence # update_column wie folgt:
Model.update_column(field, value)
Wenn das Ziel darin besteht, einen Datensatz einfach ohne Rückrufe oder Validierungen einzufügen oder zu aktualisieren, und Sie möchten dies tun, ohne auf zusätzliche Gems zurückgreifen zu müssen, bedingte Prüfungen hinzuzufügen, RAW SQL zu verwenden oder den vorhandenen Code auf irgendeine Weise zu ändern Es ist möglich, ein "Schattenobjekt" zu verwenden, das auf Ihre vorhandene Db-Tabelle zeigt. So wie:
class ImportedUser < ActiveRecord::Base
# To import users with no validations or callbacks
self.table_name = 'users'
end
Dies funktioniert mit jeder Rails-Version, ist Thread-sicher 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.
ImportedUser.new( person_attributes )
Mein Take war so (Anmerkung: dies deaktiviert Callbacks beim Erstellen, Aktualisieren, Löschen und anderen, 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
Ich würde empfehlen, den skip_callback-Ansatz NICHT zu verwenden, da er nicht threadsicher ist. Der hinterlistige Save-Edelstein ist jedoch da es gerade SQL läuft. Beachten Sie, dass dies keine Validierungen auslöst. Sie müssen sie also selbst aufrufen (z. B. mein_modell.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!
Ich habe ein einfaches Juwel geschrieben, um Validierungen adhoc zu überspringen, aber es könnte wahrscheinlich aktualisiert werden, um auch Rückrufe zu überspringen.
https://github.com/npearson72/validation_skipper
Sie könnten den can_skip_validation_for
in den gem nehmen und Funktionen hinzufügen, um auch Rückrufe zu überspringen. Rufen Sie vielleicht die Methode can_skip_validation_and_callbacks_for
auf.
Alles andere würde gleich funktionieren. Wenn Sie dabei Hilfe benötigen, lassen Sie es mich wissen.
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, in der Methode "self" anstelle des Modellnamens zu verwenden, um die Verbindung des Namens zu vermeiden.
Ich bin auch auf einen Gist von Sven Fuchs gestoßen, der nett aussieht, hier hier
Dieser Hack hat endlich für mich funktioniert (_notify_comment_observer_for_after_create
Methode für das Objekt neu definiert):
if no_after_create_callback
def object._notify_comment_observer_for_after_create; nil; end
end
Keine 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 | |