我正在将旧的旧版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
,其他任何想法可能来自哪个?
答案 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等图形工具进行检查。