def diff(other, elements = self.class::ELEMENTS)
diffs = {}
elements.each do |element|
if other.respond_to?(element)
self_value = self.send(element)
other_value = other.send(element)
next if self_value == other_value
diffs[element] = if other_value.respond_to?(:diff)
self_value.diff(other_value)
elsif other_value.is_a?(Enumerable) && other_value.all?{|v| v.respond_to?(:diff)}
if self_value.size != other_value.size
[self_value.size, other_value.size]
else
enum_diffs = []
self_value.each_with_index do |val, index|
enum_diffs << val.diff(other_value[index], val.class::ELEMENTS)
end
enum_diffs.reject{|h| h.empty?}
end
else
[other_value, self_value] unless other_value == self_value
end
end
end
diffs
end