Module: EasyDiff::Core

Defined in:
lib/easy_diff/core.rb

Class Method Summary collapse

Class Method Details

._blank?(obj) ⇒ Boolean

Can’t use regular empty? because that affects strings.

Returns:

  • (Boolean)


77
78
79
80
81
82
83
# File 'lib/easy_diff/core.rb', line 77

def self._blank?(obj)
  if obj.is_a?(Hash) || obj.is_a?(Array)
    obj.empty?
  else
    obj.nil?
  end
end

.easy_clone(original) ⇒ Object



72
73
74
# File 'lib/easy_diff/core.rb', line 72

def self.easy_clone(original)
  Marshal::load(Marshal.dump(original))
end

.easy_diff(original, modified) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/easy_diff/core.rb', line 3

def self.easy_diff(original, modified)
  removed = nil
  added   = nil

  if original.nil?
    added = modified.safe_dup

  elsif modified.nil?
    removed = original.safe_dup

  elsif original.is_a?(Hash) && modified.is_a?(Hash)
    removed = {}
    added   = {}

    keys_in_common  = original.keys & modified.keys
    keys_removed    = original.keys - modified.keys
    keys_added      = modified.keys - original.keys

    keys_removed.each{ |key| removed[key] = original[key].safe_dup }
    keys_added.each{ |key| added[key] = modified[key].safe_dup }

    keys_in_common.each do |key|
      r, a = easy_diff original[key], modified[key]
      unless _blank?(r) && _blank?(a)
        removed[key] = r
        added[key] = a
      end
    end

  elsif original.is_a?(Array) && modified.is_a?(Array)
    removed = subtract_arrays(original, modified)
    added   = subtract_arrays(modified, original)

  elsif original != modified
    removed   = original
    added     = modified
  end

  return removed, added
end

.easy_merge!(original, added) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/easy_diff/core.rb', line 60

def self.easy_merge!(original, added)
  if original.is_a?(Hash) && added.is_a?(Hash)
    added_keys = added.keys
    added_keys.each{ |key| original[key] = easy_merge!(original[key], added[key])}
  elsif original.is_a?(Array) && added.is_a?(Array)
    original +=  added
  else
    original = added.safe_dup
  end
  original
end

.easy_unmerge!(original, removed) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/easy_diff/core.rb', line 44

def self.easy_unmerge!(original, removed)
  if original.is_a?(Hash) && removed.is_a?(Hash)
    keys_in_common = original.keys & removed.keys
    keys_in_common.each do |key|
      if original[key] == removed[key]
        original.delete(key)
      else
        easy_unmerge!(original[key], removed[key])
      end
    end
  elsif original.is_a?(Array) && removed.is_a?(Array)
    subtract_arrays!(original, removed)
  end
  original
end

.subtract_arrays(arr1, arr2) ⇒ Object

Non-destructive version of above method.



96
97
98
99
100
101
# File 'lib/easy_diff/core.rb', line 96

def self.subtract_arrays arr1, arr2
  cloned_arr1 = easy_clone(arr1)
  subtract_arrays!(cloned_arr1, arr2)

  cloned_arr1
end

.subtract_arrays!(arr1, arr2) ⇒ Object

Regular array difference does not handle duplicate values in the way that is needed for this library. Examples:

subtract_arrays([1, 1, 2, 3], [1, 2]) => [1, 3]
subtract_arrays([3, 3, 3, 4], [3, 4, 5]) => [3, 3]

Shamelessly stolen from stackoverflow.com/questions/3852755/ruby-array-subtraction-without-removing-items-more-than-once



90
91
92
93
# File 'lib/easy_diff/core.rb', line 90

def self.subtract_arrays! arr1, arr2
  counts = arr2.inject(Hash.new(0)) { |h, v| h[v] += 1; h }
  arr1.reject! { |e| counts[e] -= 1 unless counts[e].zero? }
end