Hashes to OpenStruct
Ruby continues to impress me. I don't think I've written a Perl script in a year. I really love the way it handles attributes. That's why I've come to appreciate OpenStruct. This handy class allows you to essentially create data structures on the fly.
I've also come to really love YAML as a way to represent data structures. I find it more visually appealing and easier to edit than XML. Since Ruby has a built in YAML parser, this is a match made in heaven. My one beef is that accessing nested data is a bit of a pain. Say, we have the following YAML:
invoice_number: 34843
date: 2001-01-23 00:00:00 -0600
products:
- sku : BL394D
quantity : 4
description : Basketball
price : 450.00
- sku : BL4438H
quantity : 1
description : Super Hoop
price : 2392.00
Accessing the first product's SKU, requires the following code:
>> invoice = YAML.load_file("invoice.yml")
>> invoice["products"].first["sku"]
=> "BL394D"
Wouldn't it be great if you could access it like:
>> invoice.products.first.sku
=> "BL394D"
Well, now you can. I've created a function called hashes2ostruct
that recursively converts all hashes to OpenStructs. As seems to be common with Ruby, it's not a whole of code:
require 'ostruct'
def hashes2ostruct(object)
return case object
when Hash
object = object.clone
object.each do |key, value|
object[key] = hashes2ostruct(value)
end
OpenStruct.new(object)
when Array
object = object.clone
object.map! { |i| hashes2ostruct(i) }
else
object
end
end
Now you can easily convert the hashes from YAML:
>> invoice = hashes2ostruct(YAML.load_file("invoice.yml"))
>> invoice.products.first.sku
=> "BL394D"
It also works if the top level object is an array. I've been using this code for a while, in some form or another, but figured it would be nice to share.