Created
May 16, 2012 13:50
-
-
Save rmw/2710460 to your computer and use it in GitHub Desktop.
Extend Ruby Hash with method to return a recursive OpenStruct
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
class Hash | |
# options: | |
# :exclude => [keys] - keys need to be symbols | |
def to_ostruct_recursive(options = {}) | |
convert_to_ostruct_recursive(self, options) | |
end | |
private | |
def convert_to_ostruct_recursive(obj, options) | |
result = obj | |
if result.is_a? Hash | |
result = result.dup.with_sym_keys | |
result.each do |key, val| | |
result[key] = convert_to_ostruct_recursive(val, options) unless options[:exclude].try(:include?, key) | |
end | |
result = OpenStruct.new result | |
elsif result.is_a? Array | |
result = result.map { |r| convert_to_ostruct_recursive(r, options) } | |
end | |
return result | |
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 'spec_helper' | |
describe Hash do | |
describe "#to_ostruct_recursive" do | |
describe "replace a nested hash" do | |
before do | |
@h = { :a => { :b => { :c => 1 } } } | |
@o = @h.to_ostruct_recursive | |
end | |
it "should be an OpenStruct" do | |
@o.is_a?(OpenStruct).should be_true | |
end | |
it "should have a nested OpenStruct" do | |
@o.a.should be | |
@o.a.is_a?(OpenStruct).should be_true | |
end | |
it "should have a nested nested OpenStruct" do | |
@o.a.b.should be | |
@o.a.b.is_a?(OpenStruct).should be_true | |
end | |
it "should have a nested nested nested value of 1" do | |
@o.a.b.c.should be | |
@o.a.b.c.should == 1 | |
end | |
describe "exclude a key from being converted to an OpenStruct" do | |
before do | |
@o_exclude = @h.to_ostruct_recursive({ :exclude => [:b] }) | |
end | |
it "should be an OpenStruct" do | |
@o.is_a?(OpenStruct).should be_true | |
end | |
it "should have a nested OpenStruct" do | |
@o.a.is_a?(OpenStruct).should be_true | |
end | |
it "should have a nested nested Hash" do | |
@o_exclude.a.b.is_a?(Hash).should be_true | |
@o_exclude.a.b.should == { :c => 1 } | |
end | |
end | |
end | |
describe "replace a nest hash in an array" do | |
before do | |
@h = { :a => [ {:a1 => 1 } ] } | |
@o = @h.to_ostruct_recursive | |
end | |
it "should be an OpenStruct" do | |
@o.is_a?(OpenStruct).should be_true | |
end | |
it "should have an array with 1 struct" do | |
@o.a.is_a?(Array).should be_true | |
@o.a.size.should == 1 | |
@o.a.first.is_a?(OpenStruct).should be_true | |
@o.a.first.a1.should == 1 | |
end | |
end | |
end | |
end |
+1
Very nice! Thanks for this. Is this MIT license?
THANKS SO MUCH!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is excellent. Thanks for this.