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.
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. –