Skip to content

Instantly share code, notes, and snippets.

/drill_into.rb Secret

Created March 1, 2016 18:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/677026973cb241819a23 to your computer and use it in GitHub Desktop.
Save anonymous/677026973cb241819a23 to your computer and use it in GitHub Desktop.
# This attempts to extract an element from an Array or Hash according to
# the contents of the second parameter "path_array" which can contain
# either strings or integers representing array indexes.
#
# This is very useful for parsing a URI as a query string
#
# Examples:
#
# data = { stuff: { things: [
# {foo: "baz", bird: "pink", car: "blue" },
# {foo: "blah", bird: "purple", car: "orange"}
# ] } },
#
# drill_into(data, ["stuff", "things", "0", "car"])
# => "blue"
#
# drill_into(data, ["stuff", "things", "orange", "bird"])
# => "purple"
#
# drill_into(data, ["stuff", "things"]
# => [ {foo: "baz", bird: "pink", car: "blue" }, {foo: "blah", bird: "purple", car: "orange"} ]
#
def drill_into(data, path_array)
try_find = proc do |p_data, array|
p_data.find { |a, _b|
a.find { |_k, v| v == array.first } if a.is_a?(Enumerable)
}
end
if data.is_a?(Enumerable)
s_array = path_array.map do |s|
@@index = Integer(s) rescue -1
(@@index == s.to_i) ? '*' : ".#{s}"
end
selector = ':root > ' + s_array.join(' > ')
match = JSONSelect(selector).match(data)
result = match ? match : try_find.call(data, path_array)
unless result
key = path_array.shift.to_sym
if data.is_a?(Hash)
result = drill_into(data[key], path_array) if data.key?(key)
elsif data.is_a?(Array)
result = data[@@index] if @@index >= 0
end
result ||= try_find.call(data, path_array)
if result and path_array.size > 1
path_array.shift
result = drill_into(result, path_array)
end
end
return result
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment