在Ruby 1.9.3上使用Rails 2.3编码错误

时间:2013-02-27 02:09:51

标签: mysql ruby-on-rails ruby unicode

我正在将旧的旧版Rails 2.3应用程序升级到更现代的版本并遇到编码问题。我已经阅读了我在这个问题上可以找到的所有现有答案,但我仍遇到问题。

Rails版本:2.3.17 Ruby ver:1.9.3p385

我的MySQL表是默认字符集:utf8,整理:utf8_general_ci。在1.9之前,我使用原始mysql宝石而没有发生任何事故。升级到1.9后,当它检索到任何包含utf8字符的内容时,会得到这个记录良好的问题:

ActionView::TemplateError (incompatible character encodings: ASCII-8BIT and UTF-8)

我切换到mysql2宝石,因为它具有出色的处理能力,我不再看到异常,但事情肯定不能正确编码。例如,数据库中显示为字符串Repoussé的内容由Rails呈现为Repoussé“Boat”显示为“Boatâ€等。

更多细节:

  • 当我使用ruby-mysql gem作为驱动程序时,我看到相同的结果。
  • 我在encoding: utf8
  • 的每个条目中添加了database.yml

我还在environment.rb添加了以下内容:

Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8

我发现我可能有一些不匹配的地方,旧版本的应用程序将latin1写入数据库的utf8字段或其他内容,但在{{1}中查看时所有字符都显示正确命令行客户端。

提前感谢任何建议,非常感谢!

更新:我现在相信问题是我的utf8数据正在通过二进制转换被强制转换为latin1在数据库的出路,我只是不确定在哪里。

mysql

我在database.yml中将mysql> SELECT CONVERT(CONVERT(name USING BINARY) USING latin1) AS latin1, CONVERT(CONVERT(name USING BINARY) USING utf8) AS utf8 FROM items WHERE id=myid; +-------------+----------+ | latin1 | utf8 | +-------------+----------+ | Repoussé | Repoussé | +-------------+----------+ 设置为encoding,其他任何想法可能来自哪个?

2 个答案:

答案 0 :(得分:6)

我终于弄清楚我的问题是什么。虽然我的数据库使用utf8进行编码,但原始mysql gem的应用会将latin1文本注入utf8表。

让我失望的是mysql命令行客户端的输出看起来是正确的。验证终端,数据库字段 MySQL客户端是否都在utf8中运行非常重要。

MySQL的客户端默认运行在latin1。您可以通过发出以下查询来发现它的运行情况:

show variables like 'char%';

如果utf8设置正确,您应该看到:

+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+

如果这些看起来不正确,请确保在[client]配置文件的my.cnf部分设置了以下内容:

default-character-set = utf8

添加以下内容添加到[mysqld]部分:

# use utf8 by default
character-set-server=utf8
collation-server=utf8_general_ci

确保在重新启动客户端之前重新启动mysql守护程序,然后验证。

注意:这不会更改现有数据库的字符集或排序规则,只是确保创建的任何新数据库都默认为utf8,并且客户端将显示在utf8中。

在我这样做之后,我看到mysql客户端中的字符与我从mysql2 gem中获得的字符相匹配。我还可以通过latin1暂时切换为“encoding: latin1”来验证此内容是否为database.conf

查找问题的一个非常方便的查询是使用char length来查找具有多字节字符的行:

SELECT id, name FROM items WHERE LENGTH(name) != CHAR_LENGTH(name);

有很多脚本可以将latin1内容转换为utf8,但最适合我的是将所有数据库转储为latin1并将内容重新填入{{1 }}:

utf8

我首先备份了我的主数据库,然后将其转储到测试数据库中,并在转到更正后的数据库之前进行了疯狂验证。

我的理解是,MySQL的翻译可以留下一些比较复杂的字符所需的东西,但由于我的大多数字节都是相当常见的东西(重音符号,引号等),这对我来说很有用。

一些资源在分类所有这些方面证明是非常宝贵的:

答案 1 :(得分:1)

你说在命令行客户端看起来一切正常,但是你的终端的字符编码可能没有设置为显示UTF8?要检入OS X终端,请单击终端>偏好>设置>高级>字符编码。另外,使用http://dev.mysql.com/downloads/gui-tools/5.0.html上的MySQL Query Browser等图形工具进行检查。