我们的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
我基本上是在这里结束了。有没有人知道如何做我需要的事情?
答案 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/