我正在将Rails 3.2.13应用程序从Ruby 1.8.7-p370升级到Ruby 1.9.3-p385。升级后,从数据库中检索的文本中的特殊字符会出现乱码。例如,“café”显示为“café”。我的数据库是latin1编码的。我正在使用mysql2(0.3.11),我的database.yml
看起来像这样:
development:
adapter: mysql2
encoding: latin1
database: my_db
username: root
host: localhost
(同样的问题也发生在生产环境中,它具有相同的数据库配置。)
当ActiveRecord从数据库中检索文本时,它似乎将其解码为utf-8,而不是我指定的latin1(或ISO-8859-1)。
为了诊断问题,我编写了一个Ruby脚本,它使用mysql2直接查询数据库,绕过ActiveRecord:
require 'rubygems'
require 'mysql2'
client = Mysql2::Client.new(:host => "localhost",
:username => "root",
:database => "food52_development_production",
:encoding => "latin1")
result = client.query('SELECT title FROM recipes WHERE id = 12934')
puts result.first["title"]
id为12934的食谱标题中包含“café”字样。在1.9.3中运行此脚本会输出正确解码的文本(“café”)。如果我将:encoding
选项更改为"utf-8"
,我会再次看到乱码文本(“café”)。
我还尝试在ActiveRecord::ConnectionAdapters
中放置断点,以查看Rails正在初始化Mysql2::Client
的编码配置。它按预期传递:encoding => "latin1"
。
然而:在某个地方,Rails决定将文本解码为utf-8。如何让Rails尊重我指定的latin1编码配置?在此先感谢您的帮助。
答案 0 :(得分:1)
从1.9.3开始,不推荐使用iconv。此外,Rails 3期望在所有输入上使用UTF-8编码。
话虽如此,你有几个不同的选择。第一个是非常hacky,但是如果你不想迁移你的数据,它将会起作用。
iconv库仍以gem形式提供,您应该可以在应用中手动执行这些转换。
Airbnb的那些人使用这样的帮手:
def self.convert_string_encoding(to, from, str)
if "1.9".respond_to?(:force_encoding)
str = str.dup if str.frozen?
str.encode(to, from, :undef => :replace)
else
require 'iconv'
Iconv.conv(to, from, str)
end
end
处理转化。您可以将其放在帮助视图中。
您可以详细了解他们的迁移here
问题在于尝试将rails的默认UTF-8转换回数据库的编码。
可能更有意义的是在现有数据上迁移到UTF-8。
This article seems to cover that fairly well.
我希望这有帮助!