2016-11-17 4 views
1

Я использую to_yaml для записи массива в файл YAML в Ruby. После написания файла мне нужно добавить еще одну строку или слово под директиву YAML (---) или три тире.Как вставить строку в файл YAML с помощью Ruby

Есть ли способ сделать это после того, как я напишу файл YAML? Или это просто лучший способ сделать это?

Я читал в одном из YAML файла для записи на другой:

items = YAML::load(File.open(yaml_file) 

items.each do |key, value| 
    item = items["#{key}"] 
    f = File.open("/tmp/blah.yaml", 'w') 
    f.puts item.to_yaml 
    f.close 
end 

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

--- 
- blah::words 
- blah::words 
+0

Не уверен, что я точно понимаю, что вы хотите сделать, но '# to_yaml' возвращает строку, поэтому после факта вы сможете использовать любой метод String. – moveson

+0

Обновлено мое сообщение, чтобы, надеюсь, очистить любую путаницу. Спасибо, что ответили! –

+4

Кажется, что вы читаете файл YAML за один раз, но пытаетесь записать в другой файл YAML по строкам. Написание YAML вручную по строкам очень подвержено ошибкам (и я не вижу веских причин сделать это именно так). Вместо этого создайте свою структуру данных в памяти и напишите файл YAML за один раз. – spickermann

ответ

0

YAML - это сериализованная версия объекта, будь то хеш или массив. Из-за того, как это делает сериализатор, в соответствии со спецификацией мы не можем вставлять строку в вывод любого старого места, она должна быть синтаксически правильной. И самый простой способ сделать это - позволить парсеру YAML и сериализатору обрабатывать его для вас.

Например:

require 'yaml' 

foo = {'a' => 1} 
puts foo.to_yaml 

который выводит:

--- 
a: 1 

и представляет собой простой хэш в формате YAML.

Мы можем сделать туда-обратно, показывая, что это правильно:

bar = foo.to_yaml 
YAML.load(bar) # => {"a"=>1} 

Более сложный объект показывает, как он может получить сложно:

foo = {'a' => [1,2], 'b' => {'c' => [3, 4]}} 
puts foo.to_yaml 

что приводит:

--- 
a: 
- 1 
- 2 
b: 
    c: 
    - 3 
    - 4 

Существуют и другие способы назначения массива, но это значение по умолчанию для сериализатора. Если вы добавили строку, в зависимости от того, что вы добавляете, она должна быть до a: или b:, что было бы болью при написании кода или добавлении в файл после - 4.

Вместо этого мы можем загружать и анализировать файл, но, тем не менее, мы хотим переделать результирующий объект, а затем переписать файл YAML, зная, что синтаксис будет прав.

В следующем коде, представьте, что bar является результатом использования YAML-х load_file, который считывает и анализирует файл YAML, вместо моего использования load который только разбирает сериализированную объект:

require 'yaml' 

bar = YAML.load("---\na: [1]\n") # => {"a"=>[1]} 

я могу изменить bar:

bar['b'] = {'c' => [2,3,4]} 

Вот модифицированный объект:

bar # => {"a"=>[1], "b"=>{"c"=>[2, 3, 4]}} 

и сериализации с помощью to_yaml напишут правильно YAML:

bar.to_yaml # => "---\na:\n- 1\nb:\n c:\n - 2\n - 3\n - 4\n" 

Если бы это было:

File.write('foo.yaml', bar.to_yaml) 

вы выполнили замену без каких-либо реальных хлопот.

Вместо того чтобы просто перезаписать файл, я рекомендую следовать правилам безопасной перезаписи файлов, записывая новый файл, переименовывая старый, переименовывая новое в имя старого, а затем удаляя переименованный старый файл. Это помогает убедиться, что файл не сбивается, если код или машина умирают, что приводит к потере всех ваших данных.

0

Если вы хотите что-то добавить в конец файла, а затем просто написать это между:

f.puts item.to_yaml 

и

f.close 

Однако вы должны рассмотреть возможность создания key (как уникальной) части имени файла YAML, который вы пишете. Как и ваш /tmp/blah.yaml написан для первого ключа и перезаписан для каждого следующего ключа, обработанного в цикле each, который, вероятно, не является тем, что вы хотите.

Смежные вопросы