Тор и YAML выводятся в двоичном виде? - PullRequest
12 голосов
/ 04 марта 2012

Я использую 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

Есть идеи?

Ответы [ 3 ]

14 голосов
/ 30 марта 2012

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

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

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

Вот пример 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 голосов
/ 20 октября 2012

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

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

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

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

  • # кодировка: 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 голосов
/ 23 июля 2014

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

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

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