Подтвердить что ты не робот

Thor & YAML выводится как двоичный?

Я использую Thor и пытаюсь вывести YAML в файл. В irb я получаю то, что ожидаю. Обычный текст в формате YAML. Но когда часть метода в Thor, его выход отличается...

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

Любые идеи?

4b9b3361

Ответ 1

Все строки Ruby 1.9 имеют прикрепленную к ним кодировку.

YAML кодирует некоторые строки без UTF8 в виде двоичных файлов, даже если они выглядят невиновными без каких-либо символов с высоким битом. Вы можете подумать, что ваш код всегда использует UTF8, но встроенные могут возвращать строки, отличные от UTF8 (ex File).

Чтобы избежать двоичного кодирования, убедитесь, что все ваши кодировки строк являются UTF-8 перед вызовом to_yaml. Измените кодировку с помощью метода 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

Вот пример ямля, кодирующего простые строки как двоичный

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

Ответ 2

После версии 1.9.3p125, встроенный в Ruby механизм YAML будет обрабатывать все BINARY-кодировки иначе, чем раньше. Все, что вам нужно сделать, это установить правильную кодировку, отличную от BINARY, до вашего String.to_yaml.

в Ruby 1.9, весь объект String привязал объект Encoding и, как отметил следующий блог (Джеймс Эдвард Грей II), Ruby создали три типа кодирования при создании String: http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings.

Одна из кодировок может решить вашу проблему = > Кодирование исходного кода

Это кодировка исходного кода и может быть указана путем добавления строки магического кодирования в первой строке или второй строке (если у вас есть строка sha-bang в первой строке исходного кода) код кодирования магии может быть одним из следующих:

  • # encoding: 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

Ответ 3

Я боролся с этим, используя 1.9.3p545 для Windows - просто с простым хешем, содержащим строки, и без Thor.

Жемчуг ZAML решает проблему довольно просто:

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