Last active
August 29, 2015 14:06
-
-
Save royratcliffe/9d821711bd32443d9b08 to your computer and use it in GitHub Desktop.
Converts a hash to an OpenStruct along with all its nested hashes. The hash and all its sub-hashes become OpenStruct instances in the resulting structure.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'ostruct' | |
class OpenStruct | |
def self_and_field_pairs | |
each_pair.map { |field, _| [self, field] } | |
end | |
end | |
class Hash | |
# Converts a hash to an OpenStruct along with all its nested hashes. The hash | |
# and all its sub-hashes become OpenStruct instances in the resulting | |
# structure. | |
def to_ostruct | |
top_ostruct = OpenStruct.new(self) | |
stack = top_ostruct.self_and_field_pairs | |
until stack.empty? | |
ostruct, field = stack.pop | |
case value = ostruct[field] | |
when Hash | |
ostruct[field] = sub_ostruct = OpenStruct.new(value) | |
stack += sub_ostruct.self_and_field_pairs | |
when Array | |
# When the field is an array, iterate through all its elements | |
# replacing all hashes with OpenStruct instances and push the new | |
# structure's fields to the stack for nested inspection of hashes | |
# later. | |
value.each_with_index do |element, index| | |
case element | |
when Hash | |
value[index] = sub_ostruct = OpenStruct.new(element) | |
stack += sub_ostruct.self_and_field_pairs | |
end | |
end | |
end | |
end | |
top_ostruct | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'minitest/autorun' | |
require_relative 'hash_to_ostruct' | |
class HashToOpenStructTest < Minitest::Test | |
def test_hash_to_ostruct | |
hash = { | |
alpha: 1, | |
bravo: 2, | |
charlie: 3, | |
delta: { | |
delta_1: { | |
xray: 'string1', | |
yankee: 'string2', | |
zulu: 'string3' | |
}, | |
delta_2: [ | |
:romeo, | |
:oscar, | |
{ | |
yankee: 1.23 | |
} | |
] | |
} | |
} | |
ostruct = hash.to_ostruct | |
assert_equal 1, ostruct.alpha | |
assert_equal 2, ostruct.bravo | |
assert_equal 3, ostruct.charlie | |
assert_equal 'string1', ostruct.delta.delta_1.xray | |
assert_equal 'string2', ostruct.delta.delta_1.yankee | |
assert_equal 'string3', ostruct.delta.delta_1.zulu | |
assert_includes ostruct.delta.delta_2, :romeo | |
assert_includes ostruct.delta.delta_2, :oscar | |
assert_equal 1.23, ostruct.delta.delta_2[2].yankee | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment