Skip to content

Adding option tomatch array elements when comparing #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ If you want to exclude some keys from comparison use exclusion param:
exclusion = ["from_user", "to_user_id"]
result = JsonCompare.get_diff(old, new, exclusion)

Alternative way for excluding keys from comparison:

exclusions = ["from_user", "to_user_id"]
result = JsonCompare.get_diff(old, new, excluded_key: excluded_keys)

If you want to match array elements by a certain key:

result = JsonCompare.get_diff(old, new, matching_key: "id")


## Contributing

1. Fork it
Expand Down
8 changes: 6 additions & 2 deletions lib/json-compare.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
require 'json-compare/comparer'

module JsonCompare
def self.get_diff(old, new, exclusion = [])
def self.get_diff(old, new, options = {})
if options.kind_of?(Array)
options = {:excluded_keys => options}
end
comparer = JsonCompare::Comparer.new
comparer.excluded_keys = exclusion
comparer.excluded_keys = options.delete(:excluded_keys) || []
comparer.matching_key = options.delete(:matching_key)
comparer.compare_elements(old,new)
end
end
42 changes: 25 additions & 17 deletions lib/json-compare/comparer.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module JsonCompare
class Comparer

attr_accessor :excluded_keys
attr_accessor :excluded_keys, :matching_key

def is_boolean(obj)
!!obj == obj
Expand Down Expand Up @@ -51,26 +51,34 @@ def compare_hashes(old_hash, new_hash)
end

def compare_arrays(old_array, new_array)
old_array_length = old_array.count
has_comparing_way = !matching_key.nil?
result = get_diffs_struct
new_array_index = 0
new_array_length = new_array.count
inters = [old_array.count, new_array.count].min

result = get_diffs_struct
old_array.each_with_index do |elem, index|
number = (new_array_index...new_array_length).detect do |n|
!(
has_comparing_way &&
elem.kind_of?(Hash) && elem.has_key?(matching_key) &&
new_array[n].kind_of?(Hash) && new_array[n].has_key?(matching_key)
) || new_array[n][matching_key] == elem[matching_key]
end

(0..inters).map do |n|
res = compare_elements(old_array[n], new_array[n])
result[:update][n] = res unless (res.nil? || (res.respond_to?(:empty?) && res.empty?))
if number
res = compare_elements(elem, new_array[number])
result[:update][index] = res unless (res.nil? || (res.respond_to?(:empty?) && res.empty?))
(new_array_index...number).each do |n|
result[:append][n] = new_array[n]
end
new_array_index = number + 1
else
result[:remove][index] = elem
end
end

# the rest of the larger array
if inters == old_array_length
(inters..new_array_length).each do |n|
result[:append][n] = new_array[n]
end
else
(inters..old_array_length).each do |n|
result[:remove][n] = old_array[n]
end
(new_array_index...new_array_length).each do |n|
result[:append][n] = new_array[n]
end

filter_results(result)
Expand All @@ -79,7 +87,7 @@ def compare_arrays(old_array, new_array)
def compare_hash_array(old_hash, new_array)
result = get_diffs_struct

(0..new_array.count).map do |n|
(0...new_array.count).map do |n|
next if new_array[n].nil?
if n == 0
res = compare_elements(old_hash, new_array[0])
Expand Down
81 changes: 80 additions & 1 deletion spec/lib/json-compare_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,86 @@

it "should compare arrays of fixnums" do
result = JsonCompare.get_diff([1, 2, 3], [1, 2, 3, 4])
result.should eq(:append => { 3 => 4 }, :update => { 3 => 4 })
result.should eq(:append => { 3 => 4 })
end
end


describe 'Arrays Comparison with matching condition' do
it "should treat as update" do
old = [{:id => '123'}]
new = [{:id => '456'}]
result = JsonCompare.get_diff(old, new, {})
result.should eq({
:update => {
0 => {:update => {:id => '456'}}
}
})
end

it "should treat as remove and append" do
old = [{:id => '123'}]
new = [{:id => '456'}]
result = JsonCompare.get_diff(old, new, {:matching_key => :id})
result.should eq({
:remove => {
0 => {:id => '123'}
},
:append => {
0 => {:id => '456'}
}
})
end

it "should treat as remove and append" do
old = [{:id => '123'}]
new = [{:id => '456'}, {:id => '123', :internal => true}, {:id => '789'}]
result = JsonCompare.get_diff(old, new, {:matching_key => :id})
result.should eq({
:update => {
0 => {
:append => {:internal => true}
}
},
:append => {
0 => {:id => '456'},
2 => {:id => '789'}
}
})
end

it "should follow the array's order when comparing" do
old = [{:id => '123'}, {:id => '456'}]
new = [{:id => '456'}, {:id => '123'}]
result = JsonCompare.get_diff(old, new, {:matching_key => :id})
result.should eq({
:append => {
0 => {:id => '456'}
},
:remove => {
1 => {:id => '456'}
}
})
end
end

describe 'Hash Array Comparison' do
it "should return empty hash" do
old_hash = {"ID" => "123"}
new_array = [{"ID" => "123"}]
result = JsonCompare.get_diff(old_hash, new_array)
result.should eq({})
end

it "should consider new array elements as append" do
old_hash = {"ID" => "123"}
new_array = [{"ID" => "123"}, {"ID" => "456"}]
result = JsonCompare.get_diff(old_hash, new_array)
result.should eq({
:append => {
1 => {"ID" => "456"}
}
})
end
end

Expand Down