2010-07-06 14 views
5

Thêm vào tiêu đề, khi tải dữ liệu từ ActiveRecord, mã hóa luôn được đặt thành ASCII-8Bit bất chấp những nỗ lực tốt nhất của tôi để buộc mã hóa. Tôi đã nhập càng nhiều chi tiết càng tốt ở đây để thử và xây dựng một báo cáo lỗi tốt mà ai đó có thể sử dụng để giúp tôi!ActiveRecord trả về dữ liệu trong ASCII-8Bit Theo Ruby 1.9.2-rc1

Các dự án được sử dụng các công nghệ sau:

  • Padrino Khung
  • của Ruby 1.9.2-RC2 (Cũng 1.9.1 và 1.9.2-preview3)
  • ActiveRecord
  • MySQL

(Danh sách đầy đủ)

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

Episodes Bảng:

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) 

Như bạn có thể thấy cơ sở dữ liệu chắc chắn nghĩ rằng mọi thứ nên được UTF-8; và adapter cơ sở dữ liệu quá:

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

Đó là lặp lại trong bảng điều khiển khi kiểm tra các kết nối kỷ lục hoạt động:

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

ruby-1.9.2-rc1> ActiveRecord :: Base.connection.encoding

Ruby nên biết ngôn ngữ, đây là tôi $ 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= 

Mặc dù của Ruby không được thiết lập Encoding.default_internal:

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

Tôi đã thêm một đoạn mã trong của config/boot.rb ứng dụng của tôi trông như thế này:

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

đó làm việc chính xác như bạn có thể mong đợi ... nhưng là một hack, và doesn 't giải quyết vấn đề.

Và đây là kết quả của vấn đề ở chỗ:

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 > 

tôi đã có một số thành công bằng cách ghi đè accessors, và xác định lại chúng như:

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

đâu encode! được định nghĩa here in the API docs for 1.9 - để trích dẫn nó ở đây "không có tùy chọn trả về một bản sao của str chuyển mã thành Encoding.default_internal."

Trong khi công việc của tôi xung quanh thành công, tôi rất muốn có UTF-8 sắp ra khỏi cơ sở dữ liệu, đó là những gì mã của tôi dường như chỉ ra là trường hợp.

+0

Thông tin bổ sung, điều này vẫn có vẻ là sự cố với 'activerecord-3.0.0.beta4' bằng cách sử dụng các bước điều khiển tương tự như được nêu trong tài liệu này. –

Trả lời

7

Bạn có thể cần đá quý ruby-mysql, mã hóa nhận biết trong 1,9, thay vì đá quý mysql phổ biến hơn, không phải. Xem my blog để biết chi tiết.

+0

ruby-1.9.2-rc1> e = Episode.new (: title => "Ralph is awesome") 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, đẹp ! Hy vọng đã giúp :) –

6

Đá quý mysql2 cũng nên giải quyết vấn đề này và nhanh hơn nhiều so với đá quý ruby-mysql.

+0

Cảm ơn nhận xét, đáng tiếc là đá quý mysql2 đã không hoạt động trên nền tảng của tôi vào thời điểm đó; và đó là những gì tôi đang sử dụng ngay bây giờ! Vẫn còn tín dụng cho Ralph (tôi cũng bình chọn cho bạn) bởi vì anh ta có thể đưa ra một câu trả lời hay khi tôi cần nó!) –

Các vấn đề liên quan