Ruby 1.9,MySQL字符编码问题

时间:2011-12-02 16:28:53

标签: mysql ruby encoding ruby-1.9

我们的Rails 3应用程序需要能够接受ä和こ之类的外来字符,并将它们保存到我们的MySQL数据库中,该数据库的character_set为'utf8'。

我们的一个模型运行验证,用于在保存之前去除其名称中的所有非单词字符。在Ruby 1.8.7和Rails 2中,以下就足够了:

def strip_non_words(string)
  string.gsub!(/\W/,'')
end

这剥夺了坏人物,但保留了诸如'ä','こ'和'3'之类的东西。然而,使用Ruby 1.9的新编码,该语句不再有效 - 它现在正在删除这些字符以及我们不想要的其他字符。我正试图找到一种方法来做到这一点。

将gsub更改为以下内容:

def strip_non_words(string)
  string.gsub!(/[[:punct]]/,'')
end

让字符串传递正常,但数据库会引发以下错误:

Mysql2::Error: Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation

通过Iconv运行字符串以尝试转换它,如下所示:

def strip_non_words(string)
  Iconv.conv('LATIN1', 'UTF8', string)
  string.gsub!(/[[:punct]]/,'')
end

错误的结果:

Iconv::IllegalSequence: "こäè" # "こäè" being a test string

我基本上是在这里结束了。有没有人知道如何做我需要的事情?

1 个答案:

答案 0 :(得分:1)

这最终成了一个有趣的解决方案。

我发现Ruby有一个我可以使用的正则表达式,但只适用于ASCII字符串。所以我不得不将字符串转换为ASCII,运行正则表达式,然后将其转换回提交给数据库。最终结果如下所示:

def strip_non_words(string)
  string_encoded = string.force_encoding(Encoding::ASCII_8BIT)
  string_encoded.gsub!(/\p{Word}+/, '') # non-word characters
  string_reencoded = string_encoded.force_encoding('ISO-8859-1')
  string_reencoded #return
end

事实证明,由于Ruby如何处理更改字符编码,您必须单独编码:http://ablogaboutcode.com/2011/03/08/rails-3-patch-encoding-bug-while-action-caching-with-memcachestore/