Rails 3 – Cómo manejar el error de PG carácter multibyte incompleto

En una aplicación de Rails 3.2 (Ruby 1.9.2) obtengo los siguientes errores

Se produjo un error PGE en la actualización de mobile_users #:

carácter multibyte incompleto

Estos son los errores de Postgres pero obtengo un error de SQLIte similar al realizar pruebas en los modos dev y prueba

Los parámetros que causan este error son (token de autenticación omitido deliberadamente)

* Parameters: {"mobile_user"=>{"quiz_id"=>"1", "auth"=>"xxx", "name"=>"Joaqu\xEDn"}, "action"=>"update", "controller"=>"mobile_users", "id"=>"1", "format"=>"mobile"} 

Esto viene como una solicitud JSON HTTP Put y la acción de actualización que trata esto es la siguiente

  # PUT /mobile_users/1 # PUT /mobile_users/1.xml def update @mobile_user = current_mobile_user @mobile_user.attributes = params[:mobile_user] respond_to do |format| if @mobile_user.save format.html { redirect_to(@mobile_user, :notice => 'Mobile user was successfully updated.') } format.json { head :ok } format.mobile { head :ok } format.xml { head :ok } else format.html { render :action => "edit" } format.json { render :json => @mobile_user.errors, :status => :unprocessable_entity } format.mobile { render :json => @mobile_user.errors, :status => :unprocessable_entity } format.xml { render :xml => @mobile_user.errors, :status => :unprocessable_entity } end end end 

La cadena ofensiva que se encuentra en los parámetros anteriores es “Joaqu \ xEDn”, que es perfectamente válido. La cosa es que necesito manejar todos los juegos de caracteres de cualquier idioma.

Supongo que necesitaría usar la biblioteca iconv pero para hacer eso necesitaría detectar el conjunto de caracteres para convertir a UTF8 y no tengo ni idea de cómo hacerlo.

También obtengo una secuencia de bytes no válida en UTF-8 para "name"=>"p\xEDa "

Esta:

 "Joaqu\xEDn" 

Es la versión codificada ISO-8859-1 de "Joaquín" por lo que no es válida UTF-8 y sus bases de datos tienen derecho a quejarse de ello. Si es posible, arregle sus clientes móviles para usar UTF-8 en el JSON; Si no puedes hacer eso, entonces puedes arreglar la encoding con esto:

 params[:mobile_user][:name].force_encoding('iso-8859-1').encode!('utf-8') 

en el servidor El problema con solucionarlo en el servidor es que tiene que adivinar cuál es la encoding entrante y su conjetura podría no ser correcta. No hay forma de adivinar de manera confiable la encoding de una cadena en particular, hay rchardet pero no funciona con versiones recientes de Ruby y parece que se ha abandonado; usted podría ser capaz de arreglar esta joya para trabajar con Ruby moderno. Hay algunas otras bibliotecas de adivinanzas, pero todas parecen haber sido abandonadas también.

El texto JSON siempre está, por definición , Unicode y UTF-8 codificado de forma predeterminada:

 3. Encoding JSON text SHALL be encoded in Unicode. The default encoding is UTF-8. 

Cualquier cliente que le envíe JSON que no esté en UTF-8 está IMO roto porque casi todo asumirá que JSON será UTF-8. Por supuesto, podría haber un encabezado de encoding en algún lugar que especifique ISO 8859-1 o tal vez los encabezados digan UTF-8 aunque sea ISO 8859-1.

Tuve el mismo problema con los datos generados por los usuarios al analizar archivos y los resolví de esta manera:

 require 'iconv' .... line = Iconv.conv('UTF-8//IGNORE', 'UTF-8', line) #now variable line has valid utf-8 data 

Puede intentar anular el configurador ‘nombre’, de modo que elimine los caracteres que no sean utf8:

 def name=(name) write_attribute(:name, Iconv.conv('UTF-8//IGNORE', 'UTF-8', name)) end