2012-03-03 41 views
12

我正在使用Thor並嘗試將YAML輸出到文件。在irb我得到了我的期望。 YAML格式的純文本。但是,當Thor的一部分方法,其輸出是不同的...Thor&YAML輸出爲二進制?

class Foo < Thor 
    include Thor::Actions 

    desc "bar", "test" 
    def set 
    test = {"name" => "Xavier", "age" => 30} 
    puts test 
    # {"name"=>"Xavier", "age"=>30} 
    puts test.to_yaml 
    # !binary "bmFtZQ==": !binary |- 
    # WGF2aWVy 
    # !binary "YWdl": 30 
    File.open("data/config.yml", "w") {|f| f.write(test.to_yaml) } 
    end 
end 

任何想法?

+1

我只是跑你的例子,它給了我完全沒有輸出。我跑了0.14.6。 – Maran 2012-03-03 23:14:11

+0

感謝您花時間檢查。在這一點上我不知道該怎麼做。我使用Ruby 1.9.3p125,如果這樣做有什麼不同的話。 :) – cp3 2012-03-04 02:00:42

+1

我安裝了1.9。3並再次運行,實際上是二進制輸出。我注意到YAML在安裝過程中得到了升級。這可能與該升級版本有關。 – Maran 2012-03-04 08:05:18

回答

14

所有Ruby 1.9字符串都附有一個編碼。

YAML將一些非UTF8字符串編碼爲二進制,即使它們看起來無辜,沒有任何高位字符。你可能會認爲你的代碼總是使用UTF8,但是builtins可以返回非UTF8字符串(例如File path例程)。

要避免二進制編碼,請在調用to_yaml之前確保所有字符串編碼都是UTF-8。使用force_encoding(「UTF-8」)方法更改編碼。

例如,我這是怎麼編碼我的選擇散列到YAML:

options = { 
    :port => 26000, 
    :rackup => File.expand_path(File.join(File.dirname(__FILE__), "../sveg.rb")) 
} 
utf8_options = {} 
options.each_pair { |k,v| utf8_options[k] = ((v.is_a? String) ? v.force_encoding("UTF-8") : v)} 
puts utf8_options.to_yaml 

這裏是YAML編碼簡單的字符串作爲二進制

>> x = "test" 
=> "test" 
>> x.encoding 
=> #<Encoding:UTF-8> 
>> x.to_yaml 
=> "--- test\n...\n" 
>> x.force_encoding "ASCII-8BIT" 
=> "test" 
>> x.to_yaml 
=> "--- !binary |-\n dGVzdA==\n" 
7

的例子後的版本1.9.3p125,紅寶石內置的YAML引擎將以不同於以前的方式對待所有BINARY編碼。你所需要做的就是在你的String.to_yaml之前設置正確的非二進制編碼。

在紅寶石1.9,所有字符串對象附加一個編碼對象 和如以下博客(由James愛德華格雷II)提到的,紅寶石已經建立在三個類型的編碼時,產生字符串: http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings

一個編碼的可能解決問題=>源代碼編碼

這是您的源代碼的編碼,並且可以通過在所述第一線路或第二線路添加魔編碼串(如果有一個是指定SHA-爆炸串在你的源代碼的第一行) 魔術編碼代碼可能是下列之一:

  • #編碼:UTF-8
  • #編碼:UTF-8
  • # - - 編碼:UTF-8 - -

所以你的情況,如果你使用Ruby 1.9.3p125或更高版本,這應該是在你的代碼的開頭加入魔術編碼的一個解決。

# encoding: utf-8 
require 'thor' 
class Foo < Thor 
    include Thor::Actions 

    desc "bar", "test" 
    def bar 
    test = {"name" => "Xavier", "age" => 30} 
    puts test 
    #{"name"=>"Xavier", "age"=>30} 
    puts test["name"].encoding.name 
    #UTF-8 
    puts test.to_yaml 
    #--- 
    #name: Xavier 
    #age: 30 
    puts test.to_yaml.encoding.name 
    #UTF-8 
    end 
end 
0

我一直在使用1.9.3p545在Windows上苦苦掙扎 - 只是使用包含字符串的簡單哈希函數 - 而沒有Thor。

寶石ZAML解決了這個問題很簡單:

require 'ZAML' 
yaml = ZAML.dump(some_hash) 
File.write(path_to_yaml_file, yaml)