rails,ajax,charset (ii)
Posted by javier ramirez on December 3, 2006
Como veíamos aquí cuando utilizamos ajax y rails tenemos que ser cuidadosos si queremos usar un juego de caracteres distinto a UTF-8. Ya hemos resuelto cómo mostrar correctamente la información que traemos desde el servidor, pero todavía tenemos que resolver cómo enviarla correctamente.
Cuando usamos los helpers de rails, las llamadas ajax funcionan enviando la información al servidor serializada mediante la función “serialize” definida en prototype.js. Esta función a su vez utiliza por debajo la llamada a la función javascript estándar “encodeURIComponent”. Por último, esta función hace un encoding pasando primero del charset que tenga la página a UTF-8 y luego escapando los caracteres.
Como resultado, cualquier llamada vía ajax que hagamos a través de prototype.js va a llegar al servidor con los parámetros en UTF-8. Una vez conscientes de este mecanismo, la forma de solucionarlo es simplemente convertir cada parámetro que recibamos en el servidor al encoding deseado, para lo que podemos usar Iconv.
Para evitar tener que pasar cada parámetro al encoding deseado, podemos hacer algo mucho más simple, consistente en convertir todos los parámetros del objeto “params”, de forma que no tenemos que andar en cada acción discriminando qué tenemos que convertir y qué no. Obviamente esto lo haremos solamente cuando detectemos que la llamada se hizo vía ajax.
Para mayor comodidad, lo que he hecho en mi caso es definir una función nueva llamada “iconv”, para la clase Hash, que directamente me recorre una Hash y todos sus hijos (siempre que soporten el método iconv), convirtiendo todas las cadenas que encuentra al encoding deseado. El código necesario para esto lo muestro a continuación:
class Hash
#converts the encoding of all the values in the (can be nested) hash,by using iconv
def iconv(c_to,c_from,obj_iconv=nil)
obj_iconv = obj_iconv || Iconv.new(c_to,c_from )
self.each do |key,value|
next if value.blank?
if value.is_a? String
self[key] = obj_iconv.iconv(value)
elsif value.respond_to? ‘iconv’
self[key] = value.iconv(c_to,c_from,obj_iconv)
end
end
return self
end
end
Este código convertirá las Strings (y las Strings dentro de una Hash) que encuentre en el objeto que se le pase. Normalmente no necesitaremos nada más, pero si fuera necesario implementar la funcionalidad para Arrays u otros objetos, sería trivial definir un método “iconv” que los recorra de forma análoga al mostrado.
Ahora ya todo lo que tenemos que hacer es definir un filtro para todas nuestras acciones o bien escribir al principio de cada una el siguiente código
params.iconv(‘iso-8859-1′,’utf-8’) if request.xhr?
Y ya podemos ser felices escribiendo y aceptando cadenas en nuestro propio idioma.
searchwords: charset, utf-8, iso-8859-1, iconv, prototype.js, javascript, encodeURIComponent, ajax
Leave a Reply