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