ActionView::Template::Error(不兼容的字符编码:UTF-8和ASCII-8BIT)

15

我正在使用Ruby 1.9.2,Rails 3.0.4/3.0.5和Phusion Passenger 3.0.3/3.0.4。我的模板是用HAML编写的,我正在使用MySQL2 gem。我的控制器动作在传递一个带有特殊字符(如umlaut)的参数时,会给我以下错误:

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

这个错误指向我的HAML模板的第一行,其中包含以下代码:

<!DOCTYPE html>

我的理解是由于我正在将一个UTF-8字符串与ASCII-8BIT字符串连接在一起,导致了这个错误,但我无法找出那个ASCII-8BIT字符串是什么。我已经检查了操作参数是否使用UTF-8进行了编码,并在HAML模板和Ruby文件的顶部添加了encoding: UTF-8声明,但仍然存在此问题。我的application.rb文件中也有一个config.encoding = "UTF-8"声明,并且以下所有内容都采用UTF-8格式:

ENV['LANG']
__ENCODING__
Encoding.default_internal
Encoding.default_external

问题在于:我无法在我的 Mac-OSX 上使用独立的 passenger 或 mongrel 在开发或生产环境中重现此结果。我只能在运行 nginx+passenger 的 Linux 生产服务器上重现它。我已经在生产服务器的控制台中验证了后面提到的所有命令都会产生 UTF-8。

您是否遇到过相同的错误,如何解决?

2个回答

12
在进行了一些调试后,我发现问题出现在使用ActionDispatch :: Request对象时,该对象中的所有字符串都被编码为ASCII-8BIT,而不管我的应用程序是否以UTF-8编码。我不知道为什么只有在Linux上使用生产服务器时才会出现这种情况,但我假设这是Ruby或Rails中的某种怪癖,因为我无法在本地重现此错误。具体而言,错误是由类似于这样的行引起的:
@current_path = request.env['PATH_INFO']

当这个实例变量在HAML模板中打印时,由于字符串以ASCII-8BIT编码而不是UTF-8编码,导致出现错误。为了解决这个问题,我做了以下操作:

@current_path = request.env['PATH_INFO'].dup.force_encoding(Encoding::UTF_8)

是什么导致了@current_path使用了一个重复的字符串,被强制转换为正确的UTF-8编码。这个错误也可能发生在其他请求相关的数据上,比如request.headers


出现相同的错误,我想知道为什么在生产Nginx/passenger上会发生这种情况。 它的LC_All设置正确。 但是请求.env是ASCII。 在本地服务器上,它是utf-8k。 - dre-hh

9

Mysql可能是ASCII问题的根源。尝试将以下内容放入初始化程序中,以至少消除这种可能性:

require 'mysql'

class Mysql::Result
  def encode(value, encoding = "utf-8")
    String === value ? value.force_encoding(encoding) : value
  end

  def each_utf8(&block)
    each_orig do |row|
      yield row.map {|col| encode(col) }
    end
  end
  alias each_orig each
  alias each each_utf8

  def each_hash_utf8(&block)
    each_hash_orig do |row|
      row.each {|k, v| row[k] = encode(v) }
      yield(row)
    end
  end
  alias each_hash_orig each_hash
  alias each_hash each_hash_utf8
end



编辑

这可能不适用于mysql2 gem。但对于mysql有效。


我知道这个解决方案,但它是针对mysql gem而不是mysql2 gem的。Mysql2没有这个问题。此外,无论我是否查询数据库,我都会得到相同的结果。 - Pan Thomakos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接