lib/airborne/path_matcher.rb in airborne-0.0.22 vs lib/airborne/path_matcher.rb in airborne-0.0.23

- old
+ new

@@ -1,45 +1,97 @@ module Airborne module PathMatcher + def get_by_path(path, json, &block) type = false parts = path.split('.') parts.each_with_index do |part, index| if part == '*' || part == '?' + ensure_array(path, json) type = part - raise "Expected #{path} to be array got #{json.class} from JSON response" unless json.class == Array if index < parts.length.pred - json.each do |element| - sub_path = parts[(index.next)...(parts.length)].join('.') - get_by_path(sub_path, element, &block) - end + walk_with_path(type, index, path, parts, json, &block) return end next end - if /^[\d]+(\.[\d]+){0,1}$/ === part - part = part.to_i - json = json[part] - else - json = json[part.to_sym] - raise "Expected #{path} to be object or array got #{json.class} from JSON response" unless [Array, Hash, NilClass].include?(json.class) - end + json = process_json(part, json) end if type == '*' - json.each{|part| yield part} + expect_all(json, &block) elsif type == '?' - item_count = json.length - error_count = 0 - json.each do |part| - begin - yield part - rescue Exception => e - error_count += 1 - raise "Expected one object in path #{path} to match provided JSON values" if item_count == error_count - end - end + expect_one(path, json, &block) else yield json end end + + private + + def walk_with_path(type, index, path, parts, json, &block) + last_error = nil + item_count = json.length + error_count = 0 + json.each do |element| + begin + sub_path = parts[(index.next)...(parts.length)].join('.') + get_by_path(sub_path, element, &block) + rescue Exception => e + last_error = e + error_count += 1 + end + ensure_match_all(last_error) if type == '*' + ensure_match_one(path, item_count, error_count) if type == '?' + end + end + + def process_json(part, json) + if is_index?(part) + part = part.to_i + json = json[part] + else + json = json[part.to_sym] + end + json + end + + def is_index?(part) + part =~ /^\d+$/ + end + + def expect_one(path, json, &block) + item_count = json.length + error_count = 0 + json.each do |part| + begin + yield part + rescue Exception => e + error_count += 1 + ensure_match_one(path, item_count, error_count) + end + end + end + + def expect_all(json, &block) + last_error = nil + begin + json.each{|part| yield part} + rescue Exception => e + last_error = e + end + ensure_match_all(last_error) + end + + def ensure_match_one(path, item_count, error_count) + raise "Expected one object in path #{path} to match provided JSON values" if item_count == error_count + end + + def ensure_match_all(error) + raise error unless error.nil? + end + + def ensure_array(path, json) + raise "Expected #{path} to be array got #{json.class} from JSON response" unless json.class == Array + end + end end