RoUS
RoUS

Reputation: 1990

Annotating Ruby structures to include anchors/references on #to_yaml

I have some large hashes (>10⁵ keys) with interlocking structures. They're stored on disk as YAML. I'd like to avoid duplication by using anchors and references in the YAML, but I haven't been able to figure out if there's a way to do it implicitly in the hash such that the #to_yaml method will label the anchor nodes properly.

Desired YAML:

--- 
parent1:
  common-element-1: &CE1
    complex-structure-goes: here
parent2:
  uncomment-element-1:
    blah: blah
  <<: *CE1

Ruby code:

hsh = {
  'parent1' => {
    'common-element-1' => {
      'complex-structure-goes' => 'here',
    },
  'parent2' => {
    'uncommon-element-1' => {
      'blah' => 'blah',
    },
    '<<' => '*CE1',
  },
}

The reference is quite straightforward -- but how to embed the &CE1 anchor in the 'common-element-1' item in the Ruby hash?

I want to work as much as possible with native Ruby primitive types (like Hash) rather than mucking about with builders and emitters and such -- and I definitely don't want to write the YAML manually!

I've looked at Read and write YAML files without destroying anchors and aliases? and its relative, among other places, but haven't found an answer yet -- at least not that I've understood.

Thanks!

Upvotes: 3

Views: 422

Answers (1)

Nevir
Nevir

Reputation: 8101

If you use the same Ruby object, the YAML library will set up references for you:

> common = {"ohai" => "I am common"}
> doc = {"parent1" => {"id" => 1, "stuff" => common}, "parent2" => {"id" => 2, "stuff" => common}}
> puts doc.to_yaml
---
parent1:
  id: 1
  stuff: &70133422893680
    ohai: I am common
parent2:
  id: 2
  stuff: *70133422893680

I'm not sure there's a straightforward way of defining Hashes that are subsets of each other, though. Perhaps tweaking your structure a bit would be warranted?

Upvotes: 4

Related Questions