Skip to content

Instantly share code, notes, and snippets.

@pier-oliviert
Forked from cmer/hash.rb
Created December 19, 2011 14:00
Show Gist options
  • Save pier-oliviert/1497359 to your computer and use it in GitHub Desktop.
Save pier-oliviert/1497359 to your computer and use it in GitHub Desktop.
Object#value_at_keypath
class Object
# Returns the value at the specified path.
# For example, "foo.bar.baz" as a path would return the
# value at self[:foo][:bar][:baz]. If self doesn't contain one of
# the keys specified in path, It will return the farthest object found (will return self if it couldn't find anything).
#
# @param String keypath A path composed of keys separated with "." specifying a deep-nested path
# @return Object the value object
class Object
def value_at_keypath(keypath)
keypath = keypath.split(".") unless keypath.is_a?(Array)
key = keypath.shift(1)[0].to_sym
value = self
if self.is_a?(Hash) && self.has_key?(key)
value = self[key]
elsif self.respond_to?(key)
value = self.send(key)
end
if (keypath.length > 0)
return value.value_at_keypath(keypath)
else
return value
end
end
end
end
a = [1,2,4,5]
b = { :a => { :b => {:c => [1,2,3,4]}}, :b => 'bar'}
a.value_at_keypath("join") => "1245"
b.value_at_keypath("a.b.c.join") => "1234"
b.value_at_keypath("a.b.c") => [1,2,3,4]
b.value_at_keypath("b") => "bar"
b.value_at_keypath("b.e") =>
b.value_at_keypath("a.b.e") => {:c=>[1, 2, 3, 4]}
b.value_at_keypath("zing!") => {:a=>{:b=>{:c=>[1, 2, 3, 4]}}, :b=>"bar"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment