2010-12-02 8 views
2

J'ai une application Ruby/Rails.Problème d'encodage Ruby UTF8

J'ai une table d'artistes dans ma base de données postgresql que je veux interroger par son nom. J'ai quelques artistes avec des caractères portugais etc. et ai quelques problèmes les interrogeant.

Par exemple, une bande s'appelle Legião Urbana. Si je fais une recherche avec la chaîne « Legia » de mon application, je reçois les params suivants:

{"action"=>"search_artist", "q"=>"legi\343", "controller"=>"home"} 

Cependant, je reçois une erreur de la requête

Artist.all(:conditions => "name LIKE '%#{params[:q]}%'") 

PGError: ERROR: invalid byte sequence for encoding "UTF8": 0xe32527 

Que dois-je faire pour convertir en UTF8 ou résoudre ce problème de se produire en quelque sorte?

Répondre

4

Je pense que cela pourrait le faire

require 'iconv' 
Iconv.conv("UTF8", "LATIN1", params[:q]) 
5

Vous devez connaître le codage de ce paramètre dans la chaîne de requête. Ruby 1.9 inclut la prise en charge des chaînes marquées avec leurs codages. Dans Ruby 1.9, vous pouvez:

params[:q].encoding # Rails 3 on 1.9 generally presents strings in UTF-8 
params[:q].encode('utf-8') # ask Ruby to re-encode it to UTF-8 

Ensuite, vous devez convertir le paramètre de ce codage en UTF-8 avant de faire la chaîne d'interpolation (#{...} syntaxe).

Vous devez également passer le paramètre en tant que paramètre SQL, et non en utilisant l'interpolation de chaîne.

Bien sûr, cela soulève la question de sécurité, à moins que vous ne sachiez comment encoder correctement du texte pour l'utiliser dans SQL, ne jamais faire une interpolation de chaîne pour construire des fragments de chaîne SQL. Parce que les fragments SQL avec des paramètres sont rapides et faciles à faire dans Rails, vous devez les utiliser.

# Rails 2 
Artist.all(:conditions => ['name like ?', "%#{params[:q]}%"]) 
Artist.all(:conditions => ['name like :q', { :q=> "%#{params[:q]}%" }]) 

# Rails 3 
Artist.where('name like ?', "%#{params[:q]}") 
Artist.where('name like :q', :q => "%#{params[:q]}") 

injection SQL est le problème de sécurité qui se produit lorsque vous faites des chaînes chaîne d'interpolation et encodent d'une manière qui construit des fragments SQL correctes pour certaines chaînes d'entrée, mais pas pour d'autres. Dans les langages/frameworks où les paramètres sont plus difficiles à manipuler, il serait acceptable de faire une interpolation de chaîne ou une construction de chaîne (si cela reste facile à faire), tant que vous cherchez exhaustivement comment vous sont requis pour coder les chaînes interpolées afin de générer des fragments SQL corrects, quelle que soit la chaîne d'entrée. Parce que l'injection SQL est si facile à éviter avec Rails via des paramètres ordonnés ou nommés (voir les quatre exemples ci-dessus), vous ne devriez avoir aucun problème à vous assurer que vos fragments SQL sont tous sécurisés.

+0

Ok, il est plus l'encodage/que je suis en train de convertir intéressé. Comment trouvez-vous l'encodage du paramètre? Je suis conscient du problème d'injection SQL mais je voulais juste donner un exemple de la requête. – johnnymire

+0

Ok cool, des conseils sur Ruby 1.8.7? – johnnymire

+1

+1 pour "vous devez transmettre le paramètre en tant que paramètre SQL, sans utiliser l'interpolation de chaîne". –