环境:Ruby 1.9.1+Rails2.3.8

当从数据库中读取中文字符时出现如下错误(数据库为mysql UTF-8字符集):

incompatible character encodings: ASCII-8BIT and UTF-8

这个问题会有两种情况导致:

1、问题环境:模板中有<%="汉字"%>,且有UTF-8的字串变量,如I18n.t(:hello)返回的是UTF-8串。

      问题所在:Ruby 1.9.1的ERB处理编码的方式,看代码erb.rb

def compile(s)
      enc = s.encoding
      raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
      s = s.dup.force_encoding("ASCII-8BIT") # don't use constant Enoding::ASCII_8BIT for miniruby
      enc = detect_magic_comment(s) || enc

.....

 

这样,s的编码是"ASCII-8BIT",模板就是ASCII-8BIT编码,当有UTF-8的字串变量concat时,出错。

      解决方案:在 enc = detect_magic_comment(s) || enc 后添加一行 s.force_encoding(enc)

2、问题环境:数据库返回UTF-8的数据时,ActiveScaffold的列表以及查看出错,这正是我此次遇到的情况。

      问题所在:ActiveRecord返回的数据,编码成了ASCII-8BIT,看代码list_column_helps.rb,

def format_value(column_value, options = {})
        if column_empty?(column_value)
          active_scaffold_config.list.empty_field_text
        elsif column_value.is_a?(Time) || column_value.is_a?(Date)
          l(column_value, :format => options[:format] || :default)
        else
          column_value.to_s
        end
      end

我查到这里返回的值就是ASCII-8BIT编码了。查了下,从mysql_adapater出来的数据就是ASCII-8BIT的。

     解决方案:大家给点建议吧,SET NAME无效、database.yml的encoding无效。我最后是修改mysql_adapter.rb

 xxx-adapter.rb文件位于.../activerecord-2.3.8/lib/active_record/connection_adapters/目录下,为数据库驱动文件。

修改如下:

 ...

    def select(sql, name = nil)
          @connection.query_with_result = true
          result = execute(sql, name)
          rows = result.all_hashes
          result.free

#以下为新加部分

          if @config[:encoding] && @config[:encoding]=="utf8"
            rows.each do |row|
              row.each do |key, value|
                if (value.class == String)
                  value.force_encoding("UTF-8")
                end
              end
            end
          end
#以上为新加部分
          rows
        end

        ...

修改mysql_adapter.rb文件后问题得以解决。