Valider la class d'un objet

Salut,

J’ai un petit soucis lorsque je test de valider la class d’un objet:

Exemple, j’ai un model avec le schema suivant

create_table :tariffs do |t|
t.column :price, :float
end

Maintenant dans le model je voudrai valider la class de price avant
d’ajouter ou modifier un tarif.

je pensé à quelque chose du genre mais cela NE FONCTIONNE PAS:

def before_save
raise “Oops wrong class” if !self.price.is_a(Float)
end

Il semble que ruby ou rails tranforme d’office la valeur en Float, au
final si je fait:

Tariff.create(:price => ‘a10’)

Tous ce passera bien mais avec une 0 pour valeur de price. Je voudrai
plutôt recevoir une erreur, hors je n’arrive pas à trouver ou mettre ma
validation.

Dans la pratique, j’aimerai par la suite faire une petite lib ou plugin
du genre: validates_class_of fonctionnant de la sorte

validates_class_of :price, :class => Float


Sébastien Grosjean - ZenCocoon

Voici ma solution,

Sébastien Grosjean (ZenCocoon) wrote:

Maintenant dans le model je voudrai valider la class de price avant
d’ajouter ou modifier un tarif.

je pensé à quelque chose du genre mais cela NE FONCTIONNE PAS:

def before_save
raise “Oops wrong class” if !self.price.is_a(Float)
end

def before_save
raise “Oops wrong class” if !self.price_before_type_cast.is_a?(Float)
end

Dans la pratique, j’aimerai par la suite faire une petite lib ou plugin
du genre: validates_class_of fonctionnant de la sorte

validates_class_of :price, :class => Float

A venir mais en fait le nom serai certaiment plus logique en tant que
validates_type_of

Je vous tiens au courant.

Sébastien Grosjean - ZenCocoon

J’ai essayé de faire un validates_class_of hors Rails (donc ne mimant
pas leur mécanisme d’écriture de condition avant l’appel à la méthode
qui la teste), et j’ai ça :

def validates_class_of (obj, validation_params)

validates that obj is an object of validation_params[:class]

for example : validates_class_of :price, :class => Float

if eval(obj.id2name + “.class”) != validation_params[:class]
errors.add(:obj, validation_params[:message] || “should be a
#{validation_params[:class]} object”)
return false
else
return true
end

end

Seul problème :
irb(main):107:0> a = 12
=> 12
irb(main):108:0> validates_class_of :a, :class => Fixnum
NameError: undefined local variable or method a' for main:Object from ./validates_class_of.rb:9:invalidates_class_of’
from (irb):108:in eval' from ./validates_class_of.rb:9:invalidates_class_of’
from (irb):108
from :0

Je vais creuser du côté de Rails…

Salut

Ta méthode a l’air ok mais pas ton test.

Seul problème :
irb(main):107:0> a = 12
=> 12
irb(main):108:0> validates_class_of :a, :class => Fixnum
NameError: undefined local variable or method a' for main:Object from ./validates_class_of.rb:9:invalidates_class_of’
from (irb):108:in eval' from ./validates_class_of.rb:9:invalidates_class_of’
from (irb):108
from :0

Vite fait (non testé) :

class MonTest
attr_accessor :a

def validates...
end

end

t = MonTest.new
t.a = 12
t.validates… :a, :class => ‘Fixum’ # => true
t.validates… :a, :class => ‘Bignum’ # => false (en fait Error parce
que t.error, n’existe pas…)

à +
NP

Oui, dans mon test, il me jette car validates… et a ne sont pas
définis au même endroit.
Je cherchais à faire quelquechose de plus générique possible, dans
l’idée de ne pas aller coller la méthode dans Rails directement (et
histoire de ne pas devoir aller lire le code… oui, je suis
fainéant).

Merci d’avoir montrer que ça fonctionnait en tout cas ; voici le test :

[zifro@september ~]irb
irb(main):001:0> class MonTest
irb(main):002:1> attr_accessor :a
irb(main):003:1> def validates_class_of(obj, validation_params)
irb(main):004:2> if eval(obj.id2name + “.class”) !=
validation_params[:class]
irb(main):005:3> puts “Error !”
irb(main):006:3> return false
irb(main):007:3> else
irb(main):008:3* return true
irb(main):009:3> end
irb(main):010:2> end
irb(main):011:1> end
=> nil
irb(main):012:0> t = MonTest.new
=> #MonTest:0x8850f43c
irb(main):013:0> t.a = 12
=> 12
irb(main):014:0> t.validates_class_of :a, :class => Fixnum # pas
besoin des ‘’
=> true
irb(main):015:0> t.validates_class_of :a, :class => Bignum # on
indique la classe
Error !
=> false
irb(main):016:0>

Salut Guillaume,

J’ai essayé de faire un validates_class_of hors Rails (donc ne mimant
pas leur mécanisme d’écriture de condition avant l’appel à la méthode
qui la teste), et j’ai ça :

def validates_class_of (obj, validation_params)

validates that obj is an object of validation_params[:class]

for example : validates_class_of :price, :class => Float

if eval(obj.id2name + “.class”) != validation_params[:class]

Je trouve ça… assez laid pour être franc.

def validates_class(obj, klass, validation_params)
if obj.is_a?(klass)

c’est pas plus simple ?

  errors.add(:obj, validation_params[:message] || "should be a

#{validation_params[:class]} object")
return false
else
return true
end

end

РJean-Fran̤ois.

Salut Sébastien,

d’ajouter ou modifier un tarif.

je pensé à quelque chose du genre mais cela NE FONCTIONNE PAS:

def before_save
raise “Oops wrong class” if !self.price.is_a(Float)
end

validates_numericality_of :price
ne te convient pas ?

-- Jean-François.

On 9/24/06, Jean-François [email protected] wrote:

c’est pas plus simple ?
Dans ce que demandait, il voulait écrire validates_class_of “à la
Rails”, c’est-Ã -dire en lui passant le symbole de l’objet, et donc obj
est un object Symbol.
S’il peut se contenter de validates_class_of price, Fixnum, {} Ã la
place, c’est tant mieux… mais ce n’est pas ce qu’il demandait.
(et oui, l’appel au eval() est moche, mais avec les symboles c’est
tout ce que je pouvais faire)

Cordialement

Jean-François wrote:

ne te convient pas ?

Bien non en fait, car il ne me transform une String genre “a1000.00” en
Float 0

Hors je prefere qu’une faute de frappe de ce genre me retourne une
erreure plutôt que de me mettre un prix à 0.

J’ai finit de faire la lib validates_type_of, je poste une autre news
juste après.

Sébastien Grosjean - ZenCocoon

Salut,

Avoir avoir eu quelques réponses sur le sujet: “Valider la class d’un
objet”, j’ai mis en place une librairie permettant de valider le type
(ou class) d’un objet depuis un model ActiveRecord.

Cette librairie est faite dans le même principe que les autre methodes
de validation de ActiveRecord.

Si cela vous interresse: (en Anglais)

http://seb.box.re/articles/2006/09/24/validates_type_of


Sébastien Grosjean - ZenCocoon

J’oublié presque,

Sébastien Grosjean (ZenCocoon) wrote:

erreure plutôt que de me mettre un prix à 0.
En effet dans ce cas particulier je trouverai plus justifié d’utiliser
validates_numericality_of, au moins si je lui passe un String du genre
“1000.00” mon prix sera bien
assimilé.
Hors je n’ai vu aucun moyen d’utiliser des options du genre:

:allow_zero => false

qui me permettrait d’éviter le cas de la faute frappe cité ci-dessus.

Dans la pratique j’ai donc sur ma todo liste de patcher
validates_numericality_of pour lui ajouter les options suivantes:

allow_negative
allow_zero
allow_positive

toute par defaut à “true” et ayant aussi les options de messages
d’erreure suivants:

negative
zero
positive

Je vous tiens au courant une fois finit.

P.S. : Si toute fois j’ai rater une methode qui fait déjà cela je suis
plus que preneur. Mon but n’ai pas de refaire ce qui existe déjà.

P.S.2: Pour la fonction souhaiter initialement appeler
validates_class_of voir le post “Librairie: validates_type_of”


Sébastien Grosjean - ZenCocoon

Guillaume “Zifro” DESRAT wrote:

Voilà qui servira certainement !
Peut-être pourrais-tu la proposer pour être intégrée à Rails ?

En effet pourquoi pas.

<coup_de_gueule>
En revanche, j’en ai assez de lire “librairie”. En français on parle
de bibliothèque.
“library” est un “faux-ami” en anglais (comme sensitive par exemple)
Merci d’écrire des bibliothèques et non pas des librairies.
</coup_de_gueule>

Tu as raison désolé pour l’erreur. Donc voici une “library” :wink: ou
bibliothèque.

Sebastien Grosjean - ZenCocoon

Voilà qui servira certainement !
Peut-être pourrais-tu la proposer pour être intégrée à Rails ?

<coup_de_gueule>
En revanche, j’en ai assez de lire “librairie”. En français on parle
de bibliothèque.
“library” est un “faux-ami” en anglais (comme sensitive par exemple)
Merci d’écrire des bibliothèques et non pas des librairies.
</coup_de_gueule>

Sébastien :

P.S. : Si toute fois j’ai rater une methode qui fait déjà cela je suis
plus que preneur. Mon but n’ai pas de refaire ce qui existe déjà .

Voir le plug-in de Bob S. :
http://i.nfectio.us/articles/2006/01/27/defining-numericality

РJean-Fran̤ois.

Jean-François wrote:

Sébastien :

P.S. : Si toute fois j’ai rater une methode qui fait déjà cela je suis
plus que preneur. Mon but n’ai pas de refaire ce qui existe déjà.

Voir le plug-in de Bob S. :
http://i.nfectio.us/articles/2006/01/27/defining-numericality

Parfait, il semble qu’il ne manque plus qu’as relancer le core pour
ajouter à validates_numericality_of les options suivantes:

greater_than
greater_than_or_equal_to
equal_to
less_than
less_than_or_equal_to
odd
even

Merci pour le lien.

Sébastien Grosjean - ZenCocoon