Here's mine:
% cat hash_to_open_struct2.rb
require 'yaml'
require 'ostruct'
class Object
def hash_to_ostruct(visited = [])
self
end
end
class Array
def hash_to_ostruct(visited = [])
map { |x| x.hash_to_ostruct(visited) }
end
end
class Hash
def hash_to_ostruct(visited = [])
os = OpenStruct.new
each do |k, v|
item = visited.find { |x| x.first.object_id == v.object_id }
if item
os.send("#{k}=", item.last)
else
os.send("#{k}=", v.hash_to_ostruct(visited + [ [self, os] ]))
end
end
os
end
end
yaml_source = <<YAML
---
foo: 1
bar:
baz: [1, 2, 3]
quux: 42
doctors:
- William Hartnell
- Patrick Troughton
- Jon Pertwee
- Tom Baker
- Peter Davison
- Colin Baker
- Sylvester McCoy
- Paul McGann
- Christopher Eccleston
- David Tennant
- {w: 1, t: 7}
a: {x: 1, y: 2, z: 3}
YAML
evil_yaml = <<EVIL
---
&verily
lemurs:
unite: *verily
beneath:
- patagonian
- bread
- products
thusly: [1, 2, 3, 4]
EVIL
loaded = YAML.load(yaml_source).hash_to_ostruct
p loaded.bar.doctors.last.w
evil_loaded = YAML.load(evil_yaml).hash_to_ostruct
p evil_loaded.lemurs.beneath
p evil_loaded.lemurs.unite.thusly
% ruby hash_to_open_struct2.rb
1
["patagonian", "bread", "products"]
[1, 2, 3, 4]