Rails 3: Valider des modèles non Active Record
Il y a une semaine de cela, Yehuda Katz a fait un article expliquant comment, dans Rails 3, obtenir les fonctionnalités de ActiveModel dans un modèle n'utilisant pas ActiveRecord. Cela permet notamment de pouvoir utiliser les méthodes de sérialisation de Rails (export json et xml) et les validations. C'est ce second point que je vais détailler aujourd'hui parce que c'est celui que je trouve le plus intéressant.
Notez que vous devez tout d'abord avoir le gem ActiveModel 3.0.pre installé sur votre machine. Il est disponible sur gemcutter. Il vous suffit donc de faire
sudo gem install activemodel -v=3.0.pre -source=http://gemcutter.org
Prenons un fichier "test.rb", totalement intépendant de Rails. C'est juste du ruby pur et dur. Mais parce qu'on y définit une classe, on souhaite pouvoir valider le format des données passées à celle-ci.
Voici donc le contenu de notre fichier test.rb Vous noterez qu'il nous suffit d'inclure ActiveModel::Validations afin d'avoir accès à toutes ces méthodes de validations. Plutôt cool ! :)
Dès à présent, nous pouvons tester si nos validations passent !
test = Test.new('Jane', 'Doe')
p test.valid?
Mais ... Comme nous avons accès à toutes les méthodes de validation d'ActiveModel, nous pouvons créer notre propre validateur ! Constatez le "validate" que nous avons ajouté et qui empêche quelqu'un de prendre le nom de famille "Doe".
Maintenant, réexecutons notre code précédent. Notre méthode "valid?" nous retournera bien évidemment false. Et si nous faisons un print de test.errors, nous constaterons que celui-ci est un Hash contenant chacune de nos erreurs.
#<OrderedHash {:last_name=>["You must know your own name. Doe is only for anonymous guys"]}>
Vous pouvez du coup, d'une manière similaire à ce que vous faites déjà avec vos modèles ActiveRecord, valider les données de tous vos objets Ruby en utilisant ActiveModel. Par exemple si vous utilisez une solution NoSQL telle que CouchDB ou MongoDB. Ou encore sur des modèles vous permettant de faire le lien avec une API distante (XML ou JSON par exemple).
Tous vos modèles utilisent ainsi la même API, celle d'ActiveModel. Ils sont tous homogènes et vous pouvez d'autant plus aisément manipuler ceux-ci.

