0

我正在将 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 的食谱的标题中有“咖啡”一词。在 1.9.3 中运行此脚本会输出正确解码的文本(“café”)。如果我将:encoding选项更改为"utf-8",我会再次看到乱码文本(“café”)。

我还尝试在 中放置一个断点ActiveRecord::ConnectionAdapters,以查看 Rails 是如何初始化的编码配置Mysql2::Client:encoding => "latin1"正如预期的那样,它正在通过。

然而:在某个地方,Rails 决定将文本解码为 utf-8。如何让 Rails 尊重我指定的 latin1 编码配置?在此先感谢您的帮助。

4

1 回答 1

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

来处理转换。您可能会将其放入您的视图的助手中。

您可以在此处阅读有关他们迁移的更多信息

问题在于尝试将 rails 的默认 UTF-8 转换回数据库的编码时。

可能更有意义的是在现有数据上迁移到 UTF-8。

这篇文章似乎很好地涵盖了这一点。

我希望这有帮助!

于 2013-03-20T17:07:34.523 回答