Reputation: 3396
I have a ruby hash that is something like this:
myhash = { title: 'http://google.com'}
I'm trying to add this to a yaml file like this:
params['myhash'] = myhash
File.open('config.yaml', 'w') do |k|
k.write params.to_yaml
end
The problem is that YAML is removing the quotes around the links even though they are needed (they contain ':').
According to several questions on Stackoverflow, YAML should only remove the quotes when they are not needed.
I found a Solution, but it's really ugly and I prefer not to use it if there was another solution.
I suppose that yaml should be including the quotes in this case. Is there any reason why it's not doing this?
Note: the links are dynamically created
Upvotes: 1
Views: 1739
Reputation: 589
After couple hours i found it's easier in python.
usage: python quotes.py *.yml
Use ruamel to replace yaml lib, yaml lib seems not handle some UTF-8 entry
from ruamel import yaml
import io
import sys
class quote_or_literal(unicode):
pass
def str_presenter(dumper, data):
if data.count("\n"): # check for multiline string
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
else:
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
yaml.add_representer(quote_or_literal, str_presenter)
def quote_dict(d):
new = {}
for k, v in d.items():
if isinstance(v, dict):
v = quote_dict(v)
else:
v = quote_or_literal(v)
new[k] = v
return new
def ensure_quotes(path):
with io.open(path, 'r', encoding='utf-8') as stream:
a = yaml.load(stream, Loader=yaml.Loader)
a = quote_dict(a)
with io.open(path, 'w', encoding='utf-8') as stream:
yaml.dump(a, stream, allow_unicode=True,
width=1000, explicit_start=True)
if __name__ == "__main__":
for path in sys.argv[1:]:
ensure_quotes(path)
Upvotes: 1
Reputation: 6834
Quotes aren't necessary for your example string. From the specs:
Normally, YAML insists the “:” mapping value indicator be separated from the value by white space. A benefit of this restriction is that the “:” character can be used inside plain scalars, as long as it is not followed by white space.
For example:
h = { value1: 'quotes: needed', value2: 'quotes:not needed' }
puts h.to_yaml
Results in:
---
:value1: 'quotes: needed'
:value2: quotes:not needed
Upvotes: 1