wake-up-neo.com

Rails 3 überspringen Validierungen und Rückrufe

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?

69
Johnny Klassy

Das funktioniert in Rails 3:

Model.skip_callback(:create)
model.save(:validate => false)
Model.set_callback(:create)

( API-Dokumente und verwandte Frage )

118
Dinatih

Verwenden Sie ActiveRecord :: Persistence # update_column wie folgt:

Model.update_column(field, value)
29
bowsersenior

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 )
10
Brad Werth

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
2

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!
1
Eric

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.

1
Nathan

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

1
Caley Woods

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
0
TuteC

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             |                |
0
Joshua Cook