Ta mère elle référence des string ruby devant la piscine de Maubeuge
Sous ce titre primesautier se dissimule un problème idiot rencontré hier soir sur le développement de Typo que j’aurais certainement résolu plus rapidement sans un abus de mojitos.
Je voulais modifier la manière dont Typo transforme les URL en liens permanents en supprimant les caractères spéciaux et accentués. J’ai donc fait le bout de code suivant :
def stripped_title
str = self.title
accents = { ['á','à','â','ä','ã','Ã','Ä','Â','À'] => 'a',
['é','è','ê','ë','Ë','É','È','Ê'] => 'e',
['í','ì','î','ï','I','Î','Ì'] => 'i',
['ó','ò','ô','ö','õ','Õ','Ö','Ô','Ò'] => 'o',
['œ'] => 'oe',
['ß'] => 'ss',
['ú','ù','û','ü','U','Û','Ù'] => 'u',
['ç','Ç'] => 'c'
}
accents.each do |ac,rep|
ac.each do |s|
str.gsub!(s, rep)
end
end
str.gsub(/<[^>]*>/,'').to_url
endÀ priori, ça semble correct. Malheureusement, une fois la fonction exécutée, les accents ont été retirés et de str, ce qui est normal, et de self.title, ce qui l’est moins. Une autre manifestation du double effet kiss cool diront certains, mais surtout un oubli manifeste de la nature profondément objet de Ruby.
Que s’est-il passé ?
Lorsque j’ai déclaré str = self.title, je n’ai pas copié le contenu de la chaîne dans la variable str, mais j’ai fait pointer str vers self.title. Résultat, toute modification de la première entraînait obligatoirement la modification de la seconde. Pour avoir le résultat escompté j’aurais du déclarer str = String.new(self.title). Ça m’a rappelé le C et mes premiers exercices avec les pointeurs. Souvenirs.
Le code correct est donc :
def stripped_title
str = String.new(self.title)
accents = { ['á','à','â','ä','ã','Ã','Ä','Â','À'] => 'a',
['é','è','ê','ë','Ë','É','È','Ê'] => 'e',
['í','ì','î','ï','I','Î','Ì'] => 'i',
['ó','ò','ô','ö','õ','Õ','Ö','Ô','Ò'] => 'o',
['œ'] => 'oe',
['ß'] => 'ss',
['ú','ù','û','ü','U','Û','Ù'] => 'u',
['ç','Ç'] => 'c'
}
accents.each do |ac,rep|
ac.each do |s|
str.gsub!(s, rep)
end
end
str.gsub(/<[^>]*>/,'').to_url
end
Publié le 04 octobre 2007 à 19h56 Publié sous Développement
Si cet article vous a plu, suivez-moi sur Twitter
10 commentaires sur Ta mère elle référence des string ruby devant la piscine de Maubeuge »
-
Par Eric le 04 octobre 2007 à 22h38 :
-
Par FlorentG le 04 octobre 2007 à 23h34 :
En Java c’est pareil. Ou pour tout langage où les Strings sont des objets passés par référence.
@Eric : j’ai fait pareil. C’est, je pense, la meilleure solution.
Je fais d’abord une conversion utf-8 vers utf-8 avec //IGNORE pour nettoyer la string de tout caractère invalide/chelou. Puis vers US-ASCII en //TRANSLIT. Ensuite je convertis tout en minuscule, je remplace certains signes de ponctuation par des tirets. Et voilà :)
-
Par Strass le 05 octobre 2007 à 03h13 :
Je m’oppose formellement à l’utilisation d’iconv ! En effet, ça part d’un bon sentiment : un code clean de quelques lignes qui fait bien le boulot. Sauf qu’entre une Ubuntu Gutsy et mon serveur sous Debian Etch (quand même pas la mer à boire), ça ne donne pas du tout le même résultat ! Il y a sans doute une solution super géniale et sans doute très bête à ce comportement, mais avec l’utilisation d’une table de conversion comme le fait Frédéric, on est sur d’arriver au résultat escompté.
-
Par Olivier Bonnaure le 05 octobre 2007 à 09h04 :
Pour ce probl�me de pointeur, j’utilise toujours la fonction clone de Object. On aurait du donc pu faire aussi : str = self.title.clone
-
Par FlorentG le 05 octobre 2007 à 09h10 :
@Strass : ouais c’est sûr, ça peut varier, maintenant dans mon cas précis, j’ai que deux environnement à gaffer : win32 et un linux. Aussi, ne pas oublier de définire la locale (du moins sous PHP), un setlocale(‘fr_fr’) permet déjà d’avoir un comportement assez similaire d’une machine à l’autre.
-
Par pouype le 05 octobre 2007 à 09h24 :
AAahh, on va avoir des corrections totomatique des url dans le prochain typo !!! :D coool
Sinon attention, en java les strings on un comportement particulier, pas forcement très objets :p
-
Par Eric le 05 octobre 2007 à 16h44 :
@Strass:
Moi je m’oppose formellement à toute interprétation qui ne contient pas le é majuscule, le à, ou le ç majuscule. Je les utilise régulièrement quand je fais de l’écrit “réfléchi”. Comme il m’arrive de parler italien j’attend aussi les ì, ò et ù. J’impose aussi les lettres composés (e dans le o par exemple)
Le problème c’est que je ne fais pas confiance à grand monde pour ce qui est de penser à toutes les combinaisons (même en se limitant à l’europe de l’ouest). Dans une conversion en liste noire, on est sûr d’en oublier. Des gens ont très bien fait le boulot dans une bibliothèque intégrée par défaut, ça serait du gachi de ne pas l’utiliser. (et je ne parle même pas des problèmes de perf sur des gsub multiples)
-
Par Moe le 05 octobre 2007 à 23h55 :
Et Œ ? Et les autres caractères $ , : . & # ! ? * ©, comment sont-ils traités ?
-
Par Strass le 09 octobre 2007 à 12h21 :
@Eric
En fait, j’étais partie sur la transformation iconv, j’étais très fier du code : en lignes tout était fait. Mais en déployant en prod, j’ai remarqué que le comportement était un poil différent… J’en suis donc arrivé à la solution de la table de hache… Faudra que je me repenche sur le problème.
-
Par Thibaut Barrère le 30 janvier 2009 à 23h25 :
Iconv peut effectivement échouer selon les plateformes…
La lib diacritics_fu (github.com/thbar/diacritics_fu/tree) ou la méthode parameterize (dans Rails récent) peuvent gérer la suppression des diacritiques de façon portable.
Trackbacks sur Ta mère elle référence des string ruby devant la piscine de Maubeuge
Les trackbacks sont fermés pour cause de spam.
L'ergonomie web, l'utilisabilité et la qualité des logiciels sont trois grandes passions mises au services de ma profession.
Il y a plus simple : l’utilisation d’iconv
Tu convertis de ton codage classique vers US-ASCII avec l’option //TRANSLIT
Ca te fera sauter tous tes accents et tes caractères non ascii, avec pile ce qu’il faut.
Comme ça tu n’oublieras pas les majuscules accentuées, les cédilles, les tilda, etc.