【问题标题】:Upgrading Rails 3 app from Ruby 1.8.7 to 1.9.3 stops respecting latin1 encoding specification in database.yml将 Rails 3 应用程序从 Ruby 1.8.7 升级到 1.9.3 停止遵守 database.yml 中的 latin1 编码规范
【发布时间】:2013-03-20 16:10:44
【问题描述】:

我正在将 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 编码配置?提前感谢您的帮助。

【问题讨论】:

  • 您的系统规格是什么?
  • @tylerdavis,我运行的是 OS X 10.8.2,但同样的问题出现在生产环境中,即 Ubuntu。

标签: ruby-on-rails-3 character-encoding ruby-1.9 mysql2 latin1


【解决方案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.

我希望这会有所帮助!

【讨论】:

  • 所以,some_string.encode('ISO-8859-1', 'utf-8') 转换得很好:gist.github.com/hoffm/5207153 但是,我不确定如何使用这些信息来修复我的应用程序。
  • 有一些在线补丁可以用于您的数据库,或者您可以使用一次性脚本将数据库中的所有字段重新编码为 UTF-8。问题之一是,Rails 期望 UTF-8 作为默认值,因此数据重新编码脚本可能是您前进的最佳选择。 Here's an article on how to convert your database. 另一个 another article 关于 1.9 和 Rails 3 的差异。
  • 谢谢,泰勒。我计划最终进行转换,但我希望不必与 1.9 迁移同时进行。
猜你喜欢
  • 1970-01-01
  • 2012-05-03
  • 1970-01-01
  • 2022-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 1970-01-01
相关资源
最近更新 更多