ActiveRecord在Ruby 1.9.2-rc1下以ASCII-8Bit返回数据 [英] ActiveRecord returns data in ASCII-8Bit Under Ruby 1.9.2-rc1

查看:163
本文介绍了ActiveRecord在Ruby 1.9.2-rc1下以ASCII-8Bit返回数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

除了标题,当从ActiveRecord加载数据时,编码总是设置为ASCII-8Bit,尽管我尽力加强编码。我已经进入尽可能多的细节,尝试构建一个可以用来帮助我的好错误报告!



该项目正在使用以下技术: p>


  • Padrino框架

  • Ruby 1.9.2-rc2(另外1.9.1和1.9.2-preview3 )

  • ActiveRecord

  • MySQL



列表)

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

剧集表:

  MySQL的>描述情节; 
+ ---------------- + -------------- + ------ + ----- + --------- + ---------------- +
| Field |类型|空|关键|默认|额外|
+ ---------------- + -------------- + ------ + ----- + --------- + ---------------- +
| id | int(11)| NO | PRI | NULL | auto_increment |
| show_id | int(11)|是| | NULL | |
| season_id | int(11)|是| | NULL | |
| episode_number | int(11)|是| | NULL | |
|标题| varchar(255)|是| | NULL | |
|年| int(11)|是| | NULL | |
+ ---------------- + -------------- + ------ + ----- + --------- + ---------------- +
6行集(0.02秒)

mysql> SHOW CREATE TABLE episodes;
表:剧集
创建表: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` / *!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci * / |
+ ------------- + ------------------------------- -------------------------------------------------- ----------------------- +
1行(0.00秒)

正如你可以看到数据库肯定认为应该是UTF-8;和数据库适配器:

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

当检查活动记录连接时,在控制台中回显:

  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 =#<互斥量: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应该知道这个语言,这里是我的 $ 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 =

尽管Ruby没有设置 Encoding.default_internal

  $ irb --simple-prompt 
ruby​​-1.9.2-rc1> Encoding.default_internal
=>我已经在我的应用程序的 config / boot.rb中添加了一段代码片段, / code>看起来像这样:

 如果Kernel.const_defined?(Encoding)和Encoding.respond_to? (:find)和Encoding.respond_to?(:default_internal)
Encoding.default_internal = Encoding.find('UTF-8')
end

正如您所期望的那样,这是一个黑客,并没有解决问题。



这里是原位问题的输出:

  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]剧集列(0.8ms)SHOW FILES FROMepisodes
=> #< 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 =新标题
=> 新标题
ruby​​-1.9.2-rc1> nt.encoding
=> #<编码:UTF-8是氢。
ruby​​-1.9.2-rc1> e.title = nt
=> 新标题
ruby​​-1.9.2-rc1> e.title.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]剧集创建(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]剧集加载(29.5ms)SELECT * FROM`episodes` WHERE(`episodes`.`title ='新标题')LIMIT 1
=> #<编码:ASCII-8BIT>
ruby​​-1.9.2-rc1>

我通过覆盖访问器,并将其重新定义为:

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

其中 encode!被定义为 here in API文档为1.9 - 在这里引用,没有选项返回一个转码到Encoding.default_internal的副本。



虽然我的工作是成功的,我更喜欢将UTF-8从数据库中出来,这是我的代码似乎表明的情况。

解决方案

你可能需要ruby-mysql gem,这是在1.9中编码,而不是更常见的mysql gem,而不是。见我的博客的详细信息。


Further to the title, when loading data from ActiveRecord the encoding is always set to ASCII-8Bit in spite of my best efforts to force the encoding. I have entered as much detail as possible here to try and build a good error report someone could use to help me out!

The project is using the following technologies:

  • Padrino Framework
  • Ruby 1.9.2-rc2 (Also 1.9.1 and 1.9.2-preview3)
  • ActiveRecord
  • MySQL

(Full List)

$ 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 Table:

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)

As you can see the database certainly thinks that things should be UTF-8; and the database adapter too:

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

That is echoed in the console when examining the active record connection:

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 should know the language, here's my $ 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=

Although Ruby is not setting Encoding.default_internal:

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

I have added a snippet in my application's config/boot.rb that looks like this:

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

That works exactly as you might expect… but is a hack, and doesn't solve the problem.

And here's the output of the problem 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 > 

I had some success by overriding the accessors, and redefining them as:

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

Where encode! is defined here in the API docs for 1.9 - to quote it here "with no options returns a copy of str transcoded to Encoding.default_internal."

Whilst my work-arounds are successful, I would much prefer to have UTF-8 coming out of the database, which is what my code seems to indicate to be the case.

解决方案

You probably need the ruby-mysql gem, which is encoding aware in 1.9, instead of the more common mysql gem, which isn't. See my blog for details.

这篇关于ActiveRecord在Ruby 1.9.2-rc1下以ASCII-8Bit返回数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆