12

Thor を使用して、YAML をファイルに出力しようとしています。irb では、期待どおりの結果が得られます。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

何か案は?

4

3 に答える 3

14

すべての Ruby 1.9 文字列にはエンコーディングが付加されています。

YAML は、一部の非 UTF8 文字列をバイナリとしてエンコードします。それらが無害に見える場合でも、ハイビット文字を一切使用しません。コードは常に UTF8 を使用していると思われるかもしれませんが、ビルトインは非 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
=> #<Encoding:UTF-8>
>> x.to_yaml
=> "--- test\n...\n"
>> x.force_encoding "ASCII-8BIT"
=> "test"
>> x.to_yaml
=> "--- !binary |-\n  dGVzdA==\n"
于 2012-03-29T20:22:26.783 に答える
7

バージョン 1.9.3p125 以降、ruby ビルドイン YAML エンジンはすべての BINARY エンコーディングを以前とは異なる方法で処理します。String.to_yaml の前に正しい非 BINARY エンコーディングを設定するだけです。

Ruby 1.9 では、すべての String オブジェクトに Encoding オブジェクトが追加され、次のブログ (James Edward Gray II による) で言及されているように、Ruby は String が生成されるときに 3 種類のエンコーディングが組み込まれています: http://blog.grayproductions.net/articles/ ruby_19s_three_default_encodings .

エンコーディングの 1 つが問題を解決する可能性があります => ソース コード エンコーディング

これはソース コードのエンコーディングであり、1 行目または 2 行目にマジック エンコーディング文字列を追加することで指定できます (ソース コードの 1 行目にシャバン文字列がある場合) マジック エンコーディング コードは 1 つの可能性があります次の:

  • # エンコーディング: utf-8
  • # コーディング: utf-8
  • # - - エンコーディング: utf-8 - -

あなたの場合、ruby 1.9.3p125 以降を使用している場合は、コードの先頭にマジック エンコーディングの 1 つを追加することで解決するはずです。

# 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
于 2012-10-20T07:20:19.187 に答える