• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pulibrary / pdc_describe / 6f858e29-b3a3-45db-95ce-b0034d5adb12

pending completion
6f858e29-b3a3-45db-95ce-b0034d5adb12

Pull #644

circleci

mccalluc
fix typo in test to match
Pull Request #644: related objects in prov history

23 of 23 new or added lines in 4 files covered. (100.0%)

1679 of 1686 relevant lines covered (99.58%)

122.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.46
/app/services/resource_compare_service.rb
1
# frozen_string_literal: true
2

3
# Compares two PDCMetadata::Resource objects and provides a hash with the `differences`
4
#
5
# If there are no differences between the two objects `identical?` returns `true` and `differences == {}`
6
# If there are differences the `differences` hash has the following structure:
7
#
8
# ```
9
#    :field_name = [{action:, from: to:, value: }]
10
# ```
11
#
12
# The array for ``:field_name` lists all the changes that happened to the field.
13
# For single-value fields is always a single element array, for multi-value fields
14
# in can contain multiple elements.
15
#
16
# The `action` indicates whether a value changed, was added, or deleted.
17
#
18
# rubocop:disable Metrics/ClassLength
19
class ResourceCompareService
1✔
20
  attr_reader :differences
1✔
21

22
  def initialize(before, after)
1✔
23
    @before = before
40✔
24
    @after = after
40✔
25
    @differences = {}
40✔
26
    compare_resources
40✔
27
  end
28

29
  def identical?
1✔
30
    @differences == {}
36✔
31
  end
32

33
  private
1✔
34

35
    def compare_resources
1✔
36
      compare_objects(:titles)
40✔
37
      compare_objects(:creators)
40✔
38
      compare_objects(:contributors)
40✔
39
      compare_objects(:related_objects)
40✔
40
      compare_simple_values
40✔
41
      compare_rights
40✔
42
      compare_keywords
40✔
43
      compare_collection_tags
40✔
44
    end
45

46
    ##
47
    # Compares simple single values between the two resources.
48
    def compare_simple_values
1✔
49
      field_names = [:description, :publisher, :publication_year, :resource_type, :resource_type_general,
40✔
50
                     :doi, :ark, :version_number]
51

52
      field_names.each do |field_name|
40✔
53
        before_value = @before.send(field_name)
320✔
54
        after_value = @after.send(field_name)
320✔
55
        if before_value != after_value
320✔
56
          @differences[field_name] = [{ action: :changed, from: before_value, to: after_value }]
90✔
57
        end
58
      end
59
    end
60

61
    def compare_rights
1✔
62
      before_value = @before.rights&.name
40✔
63
      after_value = @after.rights&.name
40✔
64
      if before_value != after_value
40✔
65
        @differences[:rights] = [{ action: :changed, from: before_value, to: after_value }]
13✔
66
      end
67
    end
68

69
    def compare_keywords
1✔
70
      changes = compare_arrays(@before.keywords, @after.keywords)
40✔
71
      @differences[:keywords] = changes if changes.count > 0
40✔
72
    end
73

74
    def compare_collection_tags
1✔
75
      changes = compare_arrays(@before.collection_tags, @after.collection_tags)
40✔
76
      @differences[:collection_tags] = changes if changes.count > 0
40✔
77
    end
78

79
    ##
80
    # Compares two arrays of simple string values.
81
    # Returns an array with the changes (values removed, values added)
82
    def compare_arrays(before_values, after_values)
1✔
83
      changes = []
80✔
84
      removed = before_values - after_values
80✔
85
      added = after_values - before_values
80✔
86
      common = (before_values + after_values).uniq - removed - added
80✔
87

88
      before_values.each do |value|
80✔
89
        changes << { action: :removed, value: value } unless value.in?(common)
2✔
90
      end
91

92
      after_values.each do |value|
80✔
93
        changes << { action: :added, value: value } if value.in?(added)
18✔
94
      end
95

96
      changes
80✔
97
    end
98

99
    # rubocop:disable Metrics/MethodLength
100
    # rubocop:disable Metrics/AbcSize
101
    # rubocop:disable Metrics/CyclomaticComplexity
102
    # rubocop:disable Metrics/PerceivedComplexity
103
    def compare_objects(method_sym)
1✔
104
      changes = []
160✔
105
      keys_before = @before.send(method_sym).map(&:compare_value)
160✔
106
      keys_after = @after.send(method_sym).map(&:compare_value)
160✔
107

108
      removed = keys_before - keys_after
160✔
109
      added = keys_after - keys_before
160✔
110
      common = (keys_before + keys_after).uniq - removed - added
160✔
111

112
      @before.send(method_sym).each do |before_object|
160✔
113
        if before_object.compare_value.in?(common)
116✔
114
          after_object = @after.send(method_sym).find { |c| c.compare_value == before_object.compare_value }
233✔
115
          if before_object.compare_value != after_object.compare_value
60✔
116
            changes << { action: :changed, from: before_object.compare_value, to: after_object.compare_value }
×
117
          end
118
        elsif before_object.compare_value.in?(removed)
56✔
119
          changes << { action: :removed, value: before_object.compare_value }
56✔
120
        end
121
      end
122

123
      @after.send(method_sym).each do |after_object|
160✔
124
        if after_object.compare_value.in?(added)
132✔
125
          changes << { action: :added, value: after_object.compare_value }
72✔
126
        end
127
      end
128

129
      @differences[method_sym] = changes if changes.count > 0
160✔
130
    end
131
    # rubocop:enable Metrics/PerceivedComplexity
132
    # rubocop:enable Metrics/CyclomaticComplexity
133
    # rubocop:enable Metrics/AbcSize
134
    # rubocop:enable Metrics/MethodLength
135
end
136
# rubocop:enable Metrics/ClassLength
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc