Created
October 6, 2015 18:38
-
-
Save sleepingkingstudios/26f7236ee5f646403f87 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Comparator | |
def initialize(actual, expected) | |
@actual = actual | |
@expected = expected | |
@errors = Hash.new { |hsh, key| hsh[key] = [] } | |
end # constructor | |
attr_accessor :actual, :expected, :errors | |
def eql? | |
compare actual, expected, [] | |
end # method eql? | |
alias_method :valid?, :eql? | |
private | |
def compare(first, v, keys) | |
if time?(first) | |
return compare_times(first, v, keys) | |
elsif time?(v) | |
return compare_times(v, first, keys) | |
end # if | |
unless first.is_a?(v.class) | |
@errors[format_keys keys] << "expected #{v.class}, got #{first.class}" | |
return false | |
end # unless | |
case first | |
when Array | |
unless first.count == v.count | |
@errors[format_keys keys] << "expected #{first.count} items, got #{v.count} items" | |
return false | |
end # unless | |
return false unless first.map.with_index do |item, index| | |
compare(item, v[index], keys + [index]) | |
end.reduce(true) { |memo, bool| memo && bool } | |
when Hash | |
unless first.keys == v.keys | |
@errors[format_keys keys] << "expected keys #{first.keys}, got #{v.keys}" | |
return false | |
end # unless | |
return false unless first.keys.reduce(true) do |memo, key| | |
memo && compare(first[key], v[key], keys + [key]) | |
end # reduce | |
else | |
unless first == v | |
byebug | |
@errors[format_keys keys] << "expected #{first.inspect}, got #{v.inspect}" | |
return false | |
end # unless | |
end # when | |
return true | |
end # method compare | |
def compare_times(time, value, keys) | |
if value.is_a?(ActiveSupport::TimeWithZone) | |
return true if time.to_i == value.to_i | |
elsif value.is_a?(Integer) || (value.is_a?(String) && value =~ /\A\d+\z/) | |
return true if time.to_i == value.to_i | |
elsif value.is_a?(String) | |
return true if time.to_i == Time.parse(value).to_i | |
end # if-elsif | |
@errors[format_keys keys] << "expected #{time.inspect}, got #{value.inspect}" | |
false | |
end # method compare_times | |
def format_keys(keys) | |
keys.empty? ? :root : :"#{[keys.first, keys[1..-1].map { |k| "[#{key}]" }].join}" | |
end | |
def time?(value) | |
case value | |
when Time, DateTime, ActiveSupport::TimeWithZone | |
true | |
else | |
false | |
end # case | |
end # method time? | |
end # class Comparator |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment