You could do this :
hash = { 'a' => [{ 'c' => 'd', 'e' => 'f' }] }
string = "a[0]['c']"
def nested_access(object, string)
string.scan(/\w+/).inject(object) do |hash_or_array, i|
case hash_or_array
when Array then hash_or_array[i.to_i]
when Hash then hash_or_array[i] || hash_or_array[i.to_sym]
end
end
end
puts nested_access(hash, string) # => "d"
The input string is scanned for letters, underscores and digits. Everything else is ignored :
puts nested_access(hash, "a/0/c") #=> "d"
puts nested_access(hash, "a 0 c") #=> "d"
puts nested_access(hash, "a;0;c") #=> "d"
An incorrect access value will return nil.
It also works with symbol as keys :
hash = {a: [{c: "d", e: "f"}]}
puts nested_access(hash, "['a'][0]['c']")
It brings the advantage of being not too strict about user input, but it does have the drawback of not recognizing keys with spaces.
a-zA-Z0-9_?