2011-03-22 57 views
1

我已經得到了的二手一堆使用大量不同的Ruby解釋器的人gem,它包括什麼歸結爲以下代碼:處理字符串編碼與紅寶石1.8相同的代碼和1.9

res = RestClient.post(...) 
doc = REXML::Document.new(res).root 

res的內容始終是UTF-8,並且在Ruby 1.8中可以正常工作,但如果響應不是純ASCII ,則用戶的默認編碼不是UTF-8,但在Ruby 1.9下會出現此錯誤。現在

,如果我要拍關於Ruby 1.9獨自這項工作,我只是堅持res.force_encoding('utf-8')在那裏,並用它來完成,但該方法是1.9只,然後紅寶石1.8下突破:

NoMethodError: undefined method `force_encoding' for #<String:0x101318178> 

最好的解決方案能想出是這樣的,這迫使系統範圍的默認編碼爲UTF-8:

Encoding.default_external = 'UTF-8' if defined? Encoding 

更好的想法,或者這是因爲它得到好處呢?對試圖使用不同編碼的圖書館用戶是否會產生負面影響?

+0

爲了澄清,我可以依靠傳入的內容總是有效的UTF-8。 Ruby 1中的問題。9是String'res'標記了用戶的默認編碼,該編碼可能不是UTF-8,這會導致REXML陷入困境。 – jpatokal 2011-03-29 02:35:26

回答

2

我與邁克劉易斯使用respond_to,但不要在整個代碼中的任何位置使用變量res。

我看了看your code in gateway.rb,它看起來像無處不在,你使用的是res時,它會通過向make_api_request呼叫建立,所以你可以在該方法的返回語句前加上這一句:

doc = doc.force_encoding("UTF-8") if doc.respond_to?(:force_encoding) 

即使這是其他地方,但它不是字面上與你遇到的每一個字符串,我相信你可以找到一種方法來重構有意義的代碼,並在一個地方,而不是你遇到它的任何地方解決問題。

您是否遇到其他地方的問題?

+0

我沒有意識到這一點,但這並不意味着它們不存在......但您的解決方案迄今爲止是最好的! – jpatokal 2011-04-01 00:35:59

3
if res.respond_to?(:force_encoding) 
    new_contents = res.force_encoding("UTF-8") 
    else 
    new_contents = res 
    end 

我會做類似的向後兼容性。

+0

但這是一個可怕的kludge,我不想污染我的代碼的每一個創建一個像這樣的字符串的代碼... – jpatokal 2011-03-22 08:54:19

0

如果在使用此方法的特定文件中包含#encoding: utf-8標頭,它會起作用嗎?

Ruby 1.9在整個應用程序中支持不同的編碼,如果這個內容是utf-8編碼,應該可以正常工作。

Ruby 1.8會簡單地忽略#encoding標題並保持良好運行狀態。

這是一個非常簡單的方法,但我相信它值得一試!

+0

據我瞭解,文件頭控制源編碼,它僅用於用於該源文件中的字符串(例如'str =「Foo」')。它對I/O(例如Restclient)獲取的數據沒有影響,默認值由外部編碼設置。請參閱http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings。 – jpatokal 2011-03-30 01:03:24

1

據我可以從代碼片段看到,問題的原因是RestClient,它不會以正確的編碼返回字符串(在HTTP響應中指定的那個),所以我首先嚐試解決這個問題固定。如果這不能完成,那麼你可以用強制編碼的代碼(邁克劉易斯建議的方式)包裝RestClient調用。或者您正在遇到除RestClient調用之外的其他地方的問題?