samedi 20 septembre 2008

La nuit du pruriel : la chasse au bug

J'ai commencé une application rails avec une classe ruby 'eleve' . Rails doit normalement créer une table sqlite nommée 'eleves' . Pour passer du pruriel au singulier , Rails utilise un 'inflector' (fichier inflections.rb dans config/initializers).

Aprés avoir généré l'echaffaudage de la table par :
./script/generate scaffold eleve nom:string prenom:string

Puis réalisé la migration par :
rake db:migrate

J'avais une systématiquement une erreur d'exécution :
ActionView::TemplateError (undefined method `eleve_path' for
#) on line #13 of eleves/index.html.erb:

J'ai commencé à chercher sur les forums un eventuel bug de la version 2.0 de Rails , la seule indication d'un problème similaire était relatif à l'opération de transformation singulier vers pluriel de Rails. J'ai recommencé l'opération avec la classe ruby 'Foo' et là pas de problème.

Puis j'ai lancé la console de Rails et réalisé l'essai suivant :

/home/user/Premappli> ./script/console
Loading development environment (Rails 2.1.1)
>> "eleve".pluralize
=> "eleves"
>> "eleves".singularize
=> "elefe"

Et oui , si la transformation singulier => pluriel fonctionne , par contre la fonction réciproque donne un résultat incorrect.
Rails fait iune mélange des règles anglaises avec du vocabulaire francais (rappel :leaf donne leaves ) .

Pour contourner le problème il y a deux solutions :

Demander à Rails d'utiliser une nom de table bien précis puis établir une relation manuelle entre la classe et le nom de la table par l'ajout dans model/bar.rb
de la ligne : set_table_name "foos" comme par exemple :

class Bar < ActiveRecord::Base
set_table_name "foos"
end

J'ai généré une application 'gestion' et ajouté
set_table_name "eleves" dans models/gestion.rb


.L'autre solution plus élégante est surcharger la classe responsable de la transformation singulier/pluriel : inflections.rb
Comme ceci
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'eleve' ,'eleves'
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
end

Voila comment on passe une nuit à chercher un bug.

Aucun commentaire: