oh_cripes
oh_cripes

Reputation: 107

Ruby YAML write without aliases

I am writing data to yaml files from ruby and I frequently get aliases dotted about the file. Things like:

- &id001  
  somekey: somevalue
- *id001

In my case I am using the yaml files to aid readability and add names to values in the files as the existing data is just | separated values with no keys. How can I prevent the yaml files being written with aliases?

[Edit]

For further clarification here is an example of the type of data and problem.

The original data looks like:

Ham|2.00|1
Eggs|0.50|12
Milk|2.00|2

And I have written a ruby script to convert it to yaml, which also looks at an sql file to get the appropriate names. The yaml file looks like:

---
- !omap
  - name: Ham
  - &id001
    price: 2.00
  - quantity: 1
- !omap
  - name: Eggs
  - price: 0.50
  - quantity: 12
- !omap
  - name: Milk
  - *id001
  - quantity: 1

This causes a problem in large data sets because the aliases may be nowhere near each other and it makes it hard to read.

Upvotes: 5

Views: 2747

Answers (3)

chetan pawar
chetan pawar

Reputation: 485

It can be complicated to dup every object to expand aliases when YAML is too big and have nested structures.

One simple (hacky) approach I used was convert the yaml to json. and then convert it back to YAML. new YAML does not contain aliases/anchors.

require 'json'

jsonObj = oldYaml.to_json
newYaml = YAML.load(jsonObj)
print newYaml.to_yaml

Same answer on this question: How to emit YAML in Ruby expanding aliases

Upvotes: 2

Xavier Shay
Xavier Shay

Reputation: 4127

This happens because you are outputting the same object multiple times in the same document. If you do not want aliases, you need to dup the objects. Compare the following:

require 'yaml'

hash = {'a' => 1}

puts [hash, hash].to_yaml
puts
puts [hash, hash.dup].to_yaml

Output:

---
- &1
  a: 1
- *1

---
- a: 1
- a: 1

Upvotes: 2

Sérgio Gomes
Sérgio Gomes

Reputation: 720

Why are you using YAML::Omap's?

A much simpler and cleaner solution would be to first read the data into an array of hashes, as such:

a = [ {'name' => 'Ham', 'price' => 2.00, 'quantity' => 1},
      {'name' => 'Eggs', 'price' => 0.50, 'quantity' => 12},
      {'name' => 'Milk', 'price' => 2.00, 'quantity' => 2} ]

and then just do:

a.to_yaml

resulting in:

--- 
- price: 2.0
  name: Ham
  quantity: 1
- price: 0.5
  name: Eggs
  quantity: 12
- price: 2.0
  name: Milk
  quantity: 2

Would that work for you?

Upvotes: 2

Related Questions