2010-07-06 8 views
5

Además del título, al cargar datos desde ActiveRecord, la codificación siempre se establece en ASCII-8Bit a pesar de mis esfuerzos para forzar la codificación. He ingresado tantos detalles como pude aquí para tratar de crear un buen informe de error que alguien pueda usar para ayudarme.ActiveRecord devuelve datos en ASCII-8Bit Bajo Ruby 1.9.2-rc1

El proyecto es el uso de las siguientes tecnologías:

  • marco Padrino
  • de Ruby 1.9.2-rc2 (también 1.9.1 y 1.9.2-Preview3)
  • ActiveRecord
  • MySQL

(Lista completa)

$ bundle show | ack '(record|padrino)' 
    * activerecord (2.3.8) 
    * padrino (0.9.14) 
    * padrino-admin (0.9.14) 
    * padrino-core (0.9.14) 
    * padrino-gen (0.9.14) 
    * padrino-helpers (0.9.14) 
    * padrino-mailer (0.9.14) 

Episodios Tabla:

mysql> DESCRIBE `episodes`; 
+----------------+--------------+------+-----+---------+----------------+ 
| Field   | Type   | Null | Key | Default | Extra   | 
+----------------+--------------+------+-----+---------+----------------+ 
| id    | int(11)  | NO | PRI | NULL | auto_increment | 
| show_id  | int(11)  | YES |  | NULL |    | 
| season_id  | int(11)  | YES |  | NULL |    | 
| episode_number | int(11)  | YES |  | NULL |    | 
| title   | varchar(255) | YES |  | NULL |    | 
| year   | int(11)  | YES |  | NULL |    | 
+----------------+--------------+------+-----+---------+----------------+ 
6 rows in set (0.02 sec) 

mysql> SHOW CREATE TABLE episodes; 
     Table: episodes 
Create Table: CREATE TABLE `episodes` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `show_id` int(11) DEFAULT NULL, 
    `season_id` int(11) DEFAULT NULL, 
    `episode_number` int(11) DEFAULT NULL, 
    `title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `year` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=74332 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 

mysql> SHOW CREATE DATABASE development; 
+-------------+--------------------------------------------------------------------------------------------------------+ 
| Database | Create Database                      | 
+-------------+--------------------------------------------------------------------------------------------------------+ 
| development | CREATE DATABASE `development` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci */   | 
+-------------+--------------------------------------------------------------------------------------------------------+ 
1 row in set (0.00 sec) 

Como se puede ver la base de datos sin duda piensa que las cosas deben ser UTF-8; y el adaptador de la base de datos también:

ActiveRecord::Base.configurations[:development] = { 
    :adapter => 'mysql', 
    :encoding => 'utf8', 
    :reconnect => false, 
    :database => "development", 
    :pool  => 5, 
    :username => 'root', 
    :password => '', 
    :host  => 'localhost', 
} 

que se repite en la consola cuando se examina la conexión activa registro:

ruby-1.9.2-rc1 > ActiveRecord::Base.connection 
    DEBUG - [06/Jul/2010 19:24:32] "SQL (0.1ms) SET NAMES 'utf8'" 
    DEBUG - [06/Jul/2010 19:24:32] "SQL (0.1ms) SET SQL_AUTO_IS_NULL=0" 
=> #<ActiveRecord::ConnectionAdapters::MysqlAdapter:0x0000010936fa88 @logger=#<Padrino::Logger:0x00000101587198 @buffer=[], @auto_flush=true, @level=0, @log=#<IO:<STDOUT>>, @mutex=#<Mutex:0x00000101587148>, @format_datetime="%d/%b/%Y %H:%M:%S", @format_message="%s - [%s] \"%s\"">, @connection=#<Mysql:0x0000010936fad8>, @runtime=0.2608299255371094, @last_verification=0, @query_cache_enabled=false, @config={:adapter=>"mysql", :encoding=>"utf8", :reconnect=>false, :database=>"development", :pool=>5, :username=>"root", :password=>"", :host=>"localhost"}, @connection_options=["localhost", "root", "", "development", nil, nil, 131072], @quoted_table_names={}, @quoted_column_names={}> 

rubí-1.9.2-RC1> ActiveRecord :: Base.connection.encoding

Rubí debe conocer el idioma, aquí está mi $ locale

LANG="en_GB.UTF-8" 
LC_COLLATE="en_GB.utf-8" 
LC_CTYPE="en_GB.utf-8" 
LC_MESSAGES="en_GB.utf-8" 
LC_MONETARY="en_GB.utf-8" 
LC_NUMERIC="en_GB.utf-8" 
LC_TIME="en_GB.utf-8" 
LC_ALL= 

A pesar de que Ruby no está fijando Encoding.default_internal:

$ irb --simple-prompt 
ruby-1.9.2-rc1 > Encoding.default_internal 
=> nil 

he añadido un fragmento de la config/boot.rb mi aplicación que tiene este aspecto:

if Kernel.const_defined?("Encoding") and Encoding.respond_to?(:find) and Encoding.respond_to?(:default_internal) 
    Encoding.default_internal = Encoding.find('UTF-8') 
end 

que funciona exactamente como se podría esperar ... pero es un truco, y doesn resolver el problema

Y aquí está la salida del problema in situ:

ruby-1.9.2-rc1 > e = Episode.new 
    DEBUG - [06/Jul/2010 19:29:14] "SQL (0.1ms) SET NAMES 'utf8'" 
    DEBUG - [06/Jul/2010 19:29:14] "SQL (0.1ms) SET SQL_AUTO_IS_NULL=0" 
    DEBUG - [06/Jul/2010 19:29:14] "Episode Columns (0.8ms) SHOW FIELDS FROM `episodes`" 
=> #<Episode id: nil, show_id: nil, season_id: nil, episode_number: nil, title: nil, year: nil> 
ruby-1.9.2-rc1 > e.title 
=> nil 
ruby-1.9.2-rc1 > nt = "New Title" 
=> "New Title" 
ruby-1.9.2-rc1 > nt.encoding 
=> #<Encoding:UTF-8> 
ruby-1.9.2-rc1 > e.title = nt 
=> "New Title" 
ruby-1.9.2-rc1 > e.title.encoding 
=> #<Encoding:UTF-8> 
ruby-1.9.2-rc1 > e.save 
    DEBUG - [06/Jul/2010 19:29:48] "SQL (0.1ms) BEGIN" 
    DEBUG - [06/Jul/2010 19:29:48] "Episode Create (0.2ms) INSERT INTO `episodes` (`show_id`, `season_id`, `episode_number`, `title`, `year`) VALUES(NULL, NULL, NULL, 'New Title', NULL)" 
    DEBUG - [06/Jul/2010 19:29:48] "SQL (0.4ms) COMMIT" 
=> true 
ruby-1.9.2-rc1 > Episode.find_by_title(nt).title.encoding 
    DEBUG - [06/Jul/2010 19:30:04] "Episode Load (29.5ms) SELECT * FROM `episodes` WHERE (`episodes`.`title` = 'New Title') LIMIT 1" 
=> #<Encoding:ASCII-8BIT> 
ruby-1.9.2-rc1 > 

que tenía cierto éxito anulando los descriptores de acceso, y la redefinición de ellos como:

class Episode 
    # ... 
    def title 
    title.encode! 
    end 
    # ... 
end 

Dónde encode! se define here in the API docs for 1.9 - a cotización aquí "sin opciones devuelve una copia de str transcodificada a Encoding.default_internal".

Aunque mis soluciones alternativas son exitosas, preferiría tener UTF-8 saliendo de la base de datos, que es lo que mi código parece indicar que es el caso.

+0

Información adicional, esto todavía parece ser un problema con 'activerecord-3.0.0.beta4' usando los mismos pasos de consola que se incluyen en este documento. –

Respuesta

7

Probablemente necesites la gema ruby-mysql, que está codificando en 1.9, en lugar de la gema mysql más común, que no lo es. Vea my blog para más detalles.

+0

ruby-1.9.2-rc1> e = Episode.new (: title => "Ralph es increíble") ruby-1.9.2-rc1> e.title.encoding => # ruby-1.9.2-rc1> e.save => true ruby-1.9.2-rc1> Episode.find_by_title (nt) .title.encoding => #

+0

Haha, nice ! Espero haber ayudado :) –

6

La gema mysql2 también debería resolver este problema, y ​​es mucho más rápida que la gema ruby-mysql.

+0

Gracias por el comentario, lamentablemente la gema mysql2 no funcionó en mi plataforma en ese momento; ¡y eso es lo que estoy usando ahora de todos modos! Aún le doy crédito a Ralph (¡lo voté de todas maneras!) Porque él pudo darme una buena respuesta cuando lo necesitaba! –

Cuestiones relacionadas