![]()
#rails Validations associatives
Lorsqu’on a une application web avec des objets associés les uns aux autres à 3 ou 4 niveaux d’imbrication et qu’on utilise la magie de Rails pour créer/Mettre à jour tout ce beau monde en une ligne qui va sauver tout ça en cascade grâce aux associations, on peut avoir des surprises. Certaines validations ne sont carrément pas effectuées ! (comme lorsqu’on utilise update_attribute)
Imaginons que j’ai un modèle Upshot (au hasard), envoyé par son propriétaire à des Clients. On obtiendrait des modèles ressemblant à ça :
- class Upshot < ActiveRecord::Base
- belongs_to :owner, :foregin_key => “user_id”, :class_name => “User”
- has_many :clients, :through => :upshotclients, :source => :user
- end
- class Upshotclient< ActiveRecord::Base
- belongs_to :upshot
- belongs_to :user
- end
- class User < ActiveRecord::Base
- has_many :upshots
- has_many :upshotclients
- validates_presence_of :email
- validates_format_of :email, :with => Authentication.email_regex
- validates_uniqueness_of :email
- end
J’ai simplifié le vrai code pour l’exemple, mais imaginez que ça peut-être beaucoup plus complexe…
Que se passera t-il si je veux créer un nouvel objet Upshot, avec des clients, dont je préciserais les emails… et dont je voudrais vérifier la validité ?
Upshot —-> Client —-> User (email)
Pour ne pas le faire à la main pour chacun des clients, j’utilise la magie de Rails dans le modèle Upshot :
- mon_nouveau_client= User.find_create(blablabla)
- self.clients.push(mon_nouveau_client)
qui me permet de créer le Client et son User associé au moment de la sauvegarde de mon Upshot
Mais malheureusement, les validations du user ne seront pas exécutées, ce qui est assez embêtant.
Et bien le magique :
- validates_associated :user
judicieusement inséré dans le modèle Client, va permettre à votre objet d’effectuer les validations du modèle User auquel il est associé !
Ainsi la validation de l’Email de mon User sera bien effectuée, et j’obtiendrai ainsi bien un message d’erreur de validation.