Thor&YAML输出为二进制?

我正在使用Thor并尝试将YAML输出到文件中。 在irb中,我得到了我的期望。 YAML格式的纯文本。 但是当Thor的一个方法的一部分,它的输出是不同的……

class Foo  "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 

有任何想法吗?

所有Ruby 1.9字符串都附加了一个编码。

YAML将一些非UTF8字符串编码为二进制,即使它们看起来很无辜,也没有任何高位字符。 您可能认为您的代码始终使用UTF8,但builtins可以返回非UTF8字符串(例如文件路径例程)。

要避免二进制编码,请在调用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 => # >> x.to_yaml => "--- test\n...\n" >> x.force_encoding "ASCII-8BIT" => "test" >> x.to_yaml => "--- !binary |-\n dGVzdA==\n" 

在版本1.9.3p125之后,ruby内置YAML引擎将以不同于之前的方式处理所有BINARY编码。 您需要做的就是在String.to_yaml之前设置正确的非BINARY编码。

在Ruby 1.9中,所有String对象都附加了一个Encoding对象,并且如下所述的博客(由James Edward Gray II提到),当生成String时,ruby已经构建了三种类型的编码: http : //blog.grayproductions.net/articles/ ruby_19s_three_default_encodings 。

其中一个编码可以解决你的问题=>源代码编码

这是源代码的编码,可以通过在第一行或第二行添加魔术编码字符串来指定(如果在源代码的第一行有一个sha-bang字符串),魔术编码代码可以是一个以下内容:

  • #encoding:utf-8
  • #coding:utf-8
  • # – – encoding:utf-8 –

所以在你的情况下,如果你使用ruby 1.9.3p125或更高版本,这应该通过在代码的开头添加一个magic编码来解决。

 # 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 

我在Windows上使用1.9.3p545一直在努力解决这个问题 – 只需要一个包含字符串的简单哈希 – 而且没有Thor。

gemZAML很简单地解决了这个问题:

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