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

Sur la tour Eiffel

Perry the Platypus wants you to subscribe now! Even if you don't visit my site on a regular basis, you can get the latest posts delivered to you for free via Email: