Method: GoodData::Helpers.diff

Defined in:
lib/gooddata/helpers/global_helpers_params.rb

.diff(old_list, new_list, options = {}) ⇒ Hash

A helper which allows you to diff two lists of objects. The objects can be arbitrary objects as long as they respond to to_hash because the diff is eventually done on hashes. It allows you to specify several options to allow you to limit on what the sameness test is done

four keys. :added contains the list that are in new_list but were not in the old_list :added contains the list that are in old_list but were not in the new_list :same contains objects that are in both lists and they are the same :changed contains list of objects that changed along ith original, the new one and the list of changes

Parameters:

  • old_list (Array<Object>)

    List of objects that serves as a base for comparison

  • new_list (Array<Object>)

    List of objects that is compared agianst the old_list

Returns:

  • (Hash)

    A structure that contains the result of the comparison. There are



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/gooddata/helpers/global_helpers_params.rb', line 149

def diff(old_list, new_list, options = {})
  old_list = old_list.map(&:to_hash)
  new_list = new_list.map(&:to_hash)

  fields = options[:fields]
  lookup_key = options[:key]

  old_lookup = Hash[old_list.map { |v| [v[lookup_key], v] }]

  res = {
    :added => [],
    :removed => [],
    :changed => [],
    :same => []
  }

  new_list.each do |new_obj|
    old_obj = old_lookup[new_obj[lookup_key]]
    if old_obj.nil?
      res[:added] << new_obj
      next
    end

    if fields
      sliced_old_obj = old_obj.slice(*fields)
      sliced_new_obj = new_obj.slice(*fields)
    else
      sliced_old_obj = old_obj
      sliced_new_obj = new_obj
    end
    if sliced_old_obj != sliced_new_obj
      difference = sliced_new_obj.to_a - sliced_old_obj.to_a
      differences = Hash[*difference.mapcat { |x| x }]
      res[:changed] << {
        old_obj: old_obj,
        new_obj: new_obj,
        diff: differences
      }
    else
      res[:same] << old_obj
    end
  end

  new_lookup = Hash[new_list.map { |v| [v[lookup_key], v] }]
  old_list.each do |old_obj|
    new_obj = new_lookup[old_obj[lookup_key]]
    if new_obj.nil?
      res[:removed] << old_obj
      next
    end
  end

  res
end