web-dev-qa-db-fra.com

Rails 3 ignorer les validations et les rappels

J'ai un modèle particulièrement complexe avec des validations et des rappels définis. Les besoins de l'entreprise appellent maintenant un scénario particulier dans lequel l'ajout d'un nouvel enregistrement nécessite l'omission des validations et des rappels. Quelle est la meilleure façon de faire cela?

69
Johnny Klassy

Cela fonctionne dans Rails 3:

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

( Documents API et question liée )

118
Dinatih

Utilisez ActiveRecord :: Persistence # update_column , comme ceci:

Model.update_column(field, value)
29
bowsersenior

Si l'objectif est simplement d'insérer ou de mettre à jour un enregistrement sans rappel ni validation, et que vous souhaitiez le faire sans recourir à des gemmes supplémentaires, sans ajout de vérifications conditionnelles, en utilisant RAW SQL ou en utilisant votre code existant de quelque manière que ce soit, cela peut être possible d'utiliser un "objet shadow" qui pointe vers votre table de base de données existante. Ainsi:

class ImportedUser < ActiveRecord::Base
  # To import users with no validations or callbacks
  self.table_name = 'users'
end

Cela fonctionne avec toutes les versions de Rails, est threadsafe et élimine complètement toutes les validations et les rappels sans modification de votre code existant. N'oubliez pas d'utiliser votre nouvelle classe pour insérer l'objet, par exemple:

ImportedUser.new( person_attributes )
10
Brad Werth

Ma prise était comme ceci (note: ceci désactive les rappels lors de la création, de la mise à jour, de la suppression et autres, vous devez les ajouter au tableau).

    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

Je recommanderais de NE PAS utiliser l'approche skip_callback car ce n'est pas thread-safe. Le sneaky save gem est cependant car il fonctionne juste SQL. Notez que cela ne déclenchera pas de validations, vous devrez donc les appeler vous-même (ex: my_model.valid?).

Voici quelques exemples de leurs documents:

# 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

J'ai écrit un petit bijou pour ignorer les validations adhoc, mais il pourrait probablement être mis à jour pour inclure également les rappels.

https://github.com/npearson72/validation_skipper

Vous pouvez prendre le can_skip_validation_for dans la gemme et ajouter une fonctionnalité pour ignorer les rappels. Peut-être appeler la méthode can_skip_validation_and_callbacks_for

Tout le reste fonctionnerait de la même manière. Si vous voulez de l'aide pour le faire, faites le moi savoir.

1
Nathan

Qu'en est-il de l'ajout d'une méthode à votre modèle qui vous permet d'ignorer les rappels?

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

Si vous finissez par utiliser quelque chose comme ceci, je vous recommanderais d'utiliser self dans la méthode au lieu du nom du modèle pour éviter la connascence de name.

J'ai aussi rencontré un Gist de Sven Fuchs qui a l'air bien, c'est ici

1
Caley Woods

Ce hack a enfin fonctionné pour moi (méthode _notify_comment_observer_for_after_create redéfinie pour l'objet):

if no_after_create_callback
  def object._notify_comment_observer_for_after_create; nil; end
end
0
TuteC

Aucun de ceux-ci ne fonctionnera si vos validations sont écrites dans la base de données elle-même.

+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+
| Field                              | Type                                             | Null | Key | Default            | Extra          |
+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+
| status                             | enum('Big','Small','Ugly','Stupid','Apologetic') | NO   |     | Stupid             |                |
0
Joshua Cook