2010-05-30 3 views
5

J'ai un objet de modèle ActiveRecord Foo; il représente une ligne de base de données standard.Prévention d'ActiveRecord save() sur une instance

Je souhaite être en mesure d'afficher les versions modifiées des instances de cet objet. Je voudrais réutiliser la classe elle-même, car elle a déjà tous les aspects dont j'aurai besoin. (Par exemple: j'ai déjà une vue qui affiche les attributs appropriés). Fondamentalement, je veux cloner l'instance du modèle, modifier certaines de ses propriétés et la renvoyer à l'appelant (vue, test, etc.).

Je fais et non que ces modifications d'attributs retournent dans la base de données. Cependant, je souhaite inclure l'attribut id dans la version clonée, car cela facilite beaucoup la gestion des routeurs. Ainsi, je prévois d'appeler ActiveRecord::Base.clone(), en définissant manuellement l'ID de l'instance clonée, puis en modifiant l'attribut approprié pour la nouvelle instance. Cela m'a inquiété cependant; un save() sur l'instance modifiée et mes données d'origine seront obturées. Donc, je cherche à verrouiller la nouvelle instance afin qu'elle ne nuise à rien d'autre. Je prévois déjà d'appeler freeze() (étant entendu que cela empêche d'autres modifications à l'objet, bien que le documentation isn't terribly clear). Cependant, je ne vois pas de moyen évident d'empêcher un save().

Quelle serait la meilleure approche pour y parvenir?

+1

Si vous avez besoin de perdre son que de manière significative avec l'objet standard ActiveRecord, il y a probablement une meilleure façon d'aborder le problème. – Matchu

+0

Je suis certainement ouvert aux alternatives –

Répondre

4

Il pourrait y avoir une façon plus idiomatique de le faire, mais une façon serait de définir un attribut virtuel et de le vérifier dans un rappel before_save. Lorsque vous clonez l'objet, définissez l'attribut virtuel - peut-être quelque chose comme is_clone à true. Puis définissez un rappel before_save pour votre classe de modèle qui empêche l'enregistrement si cet attribut est défini.

4

freeze() semble atteindre ce que je veux, bien que d'une manière laide.

x = Factory.create(:my_model) 
x.save! # true 
x.freeze 
x.save! 
TypeError: can't modify frozen hash 

Je devine que save() tente de mettre à jour les attributs modifiés créés/qui échoue parce que le hachage des attributs est gelé. Donc, la congélation empêchera la sauvegarde ... mais j'apprécierais une méthode plus fiable avec un message d'erreur plus spécifique.

+2

Juste pour clarifier, geler empêchera l'instance d'être modifiée du tout, en lecture seule! autorise les modifications mais empêche l'enregistrement de l'instance modifiée dans la base de données. –

+0

Merci pour la mise à jour @DavidAldridge; J'ai changé ma réponse acceptée. –

Questions connexes