Skip to content

Instantly share code, notes, and snippets.

@pier-oliviert
Forked from cmer/hash.rb
Created December 19, 2011 03:25
Show Gist options
  • Save pier-oliviert/1495250 to your computer and use it in GitHub Desktop.
Save pier-oliviert/1495250 to your computer and use it in GitHub Desktop.
Hash#value_at_path
class Hash
# 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, nil is returned.
#
# This method is useful as it simplifies statements such as:
# value = h[:a][:b][:c][:d] if h[:a] && h[:a][:b] && h[:a][:b][:c]
# to
# value = h.value_at_path([:a, :b, :c, :d])
#
# @param Array path An array of keys specifying a deep-nested path
# @return Object the value object
def value_at_path(path)
raise ArgumentError unless path.is_a?(Array)
raise ArgumentError if path.include?(nil)
raise ArgumentError if path.empty?
if path.size == 1
return self[path[0]]
else
if self[path[0]].respond_to?(:value_at_path)
return self[path[0]].value_at_path(path[1..-1])
else
return nil
end
end
end
end
require 'test_helper'
class HashTest < ActiveSupport::TestCase
def setup
@h = { :a => { :b => {:c => 'foo'}}, :b => 'bar'}
end
test "value_at_path returns value if path exists" do
assert_equal 'foo', @h.value_at_path([:a, :b, :c])
assert_equal 'bar', @h.value_at_path([:b])
assert_equal @h[:a], @h.value_at_path([:a])
assert_equal @h[:a][:b], @h.value_at_path([:a, :b])
end
test "value_at_path returns value if path does not exist" do
assert_nil @h.value_at_path([:a, :b, :c, :d])
assert_nil @h.value_at_path([:c])
end
test "value_at_path raises an exception if specified path is invalid" do
assert_raise(ArgumentError) { @h.value_at_path([]) }
assert_raise(ArgumentError) { @h.value_at_path([nil]) }
assert_raise(ArgumentError) { @h.value_at_path('foo') }
assert_raise(ArgumentError) { @h.value_at_path(123) }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment