2010-07-06 2 views
5

Weiter beim Titel, beim Laden von Daten von ActiveRecord die Codierung immer auf ASCII-8Bit trotz meiner besten Bemühungen, die Codierung zu erzwingen. Ich habe so viele Details wie möglich hier eingegeben, um einen guten Fehlerbericht zu erstellen, den jemand verwenden könnte, um mir zu helfen!ActiveRecord gibt Daten in ASCII-8Bit unter Ruby 1.9.2-rc1

Das Projekt wird mit den folgenden Technologien:

  • Padrino Rahmen
  • Ruby-1.9.2-RC2 (auch 1.9.1 und 1.9.2-preview3)
  • Active
  • MySQL

(Gesamtliste)

$ 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) 

Folgen Tabelle:

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) 

Wie Sie die Datenbank mit Sicherheit sehen glaubt, dass die Dinge sollte UTF-8 sein; und der Datenbank-Adapter auch:

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

die in der Konsole hallt, wenn die aktive Aufzeichnung Verbindung Prüfung:

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={}> 

Rubin-1.9.2-rc1> Active :: Base.connection.encoding

Rubin sollte die Sprache kennen, hier ist mein $ 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= 

Obwohl Ruby nicht Encoding.default_internal Einstellung:

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

Ich habe config/boot.rb einen Ausschnitt in meiner Anwendung hinzugefügt, die wie folgt aussieht:

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

, die genau wie Sie vielleicht erwarten funktioniert ... aber ist ein Hack, und doesn Löse das Problem nicht.

Und hier ist der Ausgang des Problems 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 > 

ich durch Überschreiben der Accessoren einen gewissen Erfolg hatte, und neu definiert sie als:

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

Wo encode!here in the API docs for 1.9 definiert ist - zitieren es hier "ohne Optionen gibt eine Kopie von str transcoded nach Encoding.default_internal zurück."

Während meine Workarounds erfolgreich sind, würde ich viel lieber UTF-8 aus der Datenbank kommen lassen, was mein Code scheint, um der Fall zu sein.

+0

Zusätzliche Informationen, dies scheint immer noch ein Problem mit 'activecord-3.0.0.beta4' zu sein, das die gleichen Konsolenschritte verwendet, wie sie hier enthalten sind. –

Antwort

7

Sie benötigen wahrscheinlich das ruby-mysql-Juwel, das in 1.9 die Kodierung erkennt, anstelle des gebräuchlicheren mysql-Edelsteins, was nicht der Fall ist. Einzelheiten finden Sie unter my blog.

+0

ruby-1.9.2-rc1> e = Episode.new (: title => "Ralph ist genial") ruby-1.9.2-rc1> e.title.encoding => # Rubin-1.9.2-rc1> e.save => true Rubin-1.9.2-rc1> Episode.find_by_title (nt) .title.encoding => #

+0

Haha, nice ! Hoffe, dass ich geholfen habe :) –

6

Das mysql2-Juwel sollte auch dieses Problem lösen und ist viel schneller als das Ruby-Mysql-Juwel.

+0

Danke für den Kommentar, leider hat der mysql2-Edelstein auf meiner Plattform zu der Zeit nicht funktioniert; und das benutze ich jetzt sowieso! Kredit immer noch an Ralph (Ich habe dich trotzdem gewählt), weil er eine gute Antwort hatte, wenn ich sie brauchte!) –

Verwandte Themen