Психоанализ YAML, включая комментарии

Согласно http://yaml.org/spec/current.html#id2509980 комментарии в файлах YAML представляют собой презентационную деталь и не должны быть в графе сериализации/представления (http://yaml.org/spec/current.html#representation/). Похоже, что Psych разбирается в соответствии со спецификацией и теряет комментарии, что означает, что невозможно проанализировать файл YAML и сериализовать его снова точно так же, когда файл содержит комментарии. Что, на мой взгляд, очень странно, потому что комментарии имеют значение в таком файле (например, configs).

Кто-нибудь знает, возможно ли разобрать комментарии в существующей библиотеке или это единственный способ сделать это самостоятельно?

Ответ 1

Вы можете перебирать узлы на более низком уровне, сохраняя комментарии при испускании. Кроме того, вы можете увидеть, дает ли механизм syck результат, который вы ищете.

Ответ 2

Мы также можем сделать что-то подобное, что изменит значение ключа, а также сохранит комментарии.

require 'yaml'
thing = YAML.load_file('/opt/database.yml')
hostname = thing["common"]["host_name"]
appname = thing["common"]["app_name"]
motdobj = IO.readlines('/opt/database.yml')
motdobj = motdobj.map {|s| s.gsub(hostname, "mrigesh")}
motdobj = motdobj.map {|s| s.gsub(appname, "abc")}

File.open('/opt/database.yml', "w" ) do | file1 |
    file1.puts motdobj
    file1.close
end

Ответ 3

Мне понравилась сумасшедшая идея @josh-voigts. Здесь сумасшедшая реализация. Комментарии могут чередоваться практически везде, и это работает!

require 'tempfile'

def yaml_conf_edit(fn, &block)
  conf = File.open(fn) {|f| YAML.load(f.read)}

  before = Tempfile.new('before')
  before.write(conf.to_yaml)
  before.close

  yield conf

  after = Tempfile.new('after')
  after.write(conf.to_yaml)
  after.close

  'merge #{fn} #{before.path} #{after.path}'
  before.unlink; after.unlink

  conf
end

Что вы можете использовать в чем-то вроде:

yaml_conf_edit('conf/database.yml') do |conf| 
  conf['development']['database'] = db_timestamped
end