2011-12-02 109 views
0

我們的Rails 3應用程序需要能夠接受像ä和こ這樣的外部字符,並將它們保存到我們的MySQL數據庫中,該數據庫的character_set爲'utf8'。Ruby 1.9,MySQL字符編碼問題

我們的模型之一運行一個驗證,用於在保存之前刪除名稱中的所有非單詞字符。在Ruby 1.8.7和Rails 2,以下就足夠了:

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

這剝奪了壞人的角色,但保留下來的東西,如「A」,「こ」,和「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 

我基本上在我的whits在這裏結束。有誰知道一種方法可以做我需要的嗎?

回答

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 

原來你有編碼的東西分開由於紅寶石如何處理改變字符編碼:http://ablogaboutcode.com/2011/03/08/rails-3-patch-encoding-bug-while-action-caching-with-memcachestore/