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?
Cela fonctionne dans Rails 3:
Model.skip_callback(:create)
model.save(:validate => false)
Model.set_callback(:create)
( Documents API et question liée )
Utilisez ActiveRecord :: Persistence # update_column , comme ceci:
Model.update_column(field, value)
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 )
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
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!
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.
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
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
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 | |