如果在 Ruby 1.9.2 開發 Rails 程式,最頭痛的問題應該就是編碼(Encoding)錯誤的問題。除了要考慮資料庫本身的編碼問題,所有的字串 IO 都會經過編碼處理,Ruby 1.9.2 提供了廣域設定與實體方法設定的方式,但該在什麼時機設定呢?
基本上 Yahuda Kats 已經寫了篇蠻詳盡的說明(Ruby 1.9 Encodings: A Primer and Solution for Rails),我這裡所要提的重點是,如果你的資料庫(如 MySQL)設定是用 UTF-8 做為儲存編碼,而 Web Server 所傳送的文字編碼是 ASCII-8BIT 的話(可以從 server log 得知),可能會遇到
“\xE4” from ASCII-8BIT to UTF-8
這樣的錯誤訊息,基本上可以用 Ruby 1.9.2 的廣域編碼設定來解決問題,只要在 $RAILS_ROOT/config/environment.rb 的檔案開頭加上這幾行設定即可:
if defined? Encoding
Encoding.default_internal = 'UTF-8'
Encoding.default_external = 'ASCII-8BIT'
end
這樣就可以正常地從 Web Form 裡面輸入中文,並以 UTF-8 字串儲存到資料庫中。如果 Web Server 並不是傳送 ASCII-8BIT 的話,那就要將 default_external 改成適當的編碼。
PS. 我是在 Ruby-1.9.2-head + Rails-3.0.0.beta4 + mysql-2.8.1 gem 的環境下測試,但 Ruby-1.9.2-preview3 之後應該都是同樣的解法。
PS2. Yahuda Kats 的這篇 Encodings, Unabridged 將目前 Ruby 1.9 處理 Encoding 的來由述說的很清楚,值得仔細研究。
PS3. 感謝 ihower 提醒 rails ticket #4336 有另外用 before_filter 對 params 做 force_encoding 的解法,這樣就方便看 log 做 debug。