FRESH → the Hive

Fresh from the Hive is Studio Melipone's weblog about visual delights, startup love and much more.

As opposed to whatever SEO stuff you should pay attention to this blog is run in a complete natural non sense. Enjoy!

Why don't you grab our RSS?

 

#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 :

  1. class Upshot < ActiveRecord::Base
  2.  
  3.   belongs_to :owner, :foregin_key => “user_id”, :class_name => “User”
  4.   has_many :clients, :through => :upshotclients, :source => :user
  5.  
  6. end
  7.  
  8. class Upshotclient< ActiveRecord::Base
  9.  
  10.   belongs_to :upshot
  11.   belongs_to :user
  12.  
  13. end
  14.  
  15.  
  16. class User < ActiveRecord::Base
  17.  
  18.   has_many :upshots
  19.   has_many :upshotclients
  20.  
  21.   validates_presence_of :email
  22.   validates_format_of :email, :with => Authentication.email_regex
  23.   validates_uniqueness_of :email
  24.  
  25. 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 :

  1. mon_nouveau_client= User.find_create(blablabla)
  2. 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 :

  1. 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.