eco-helpers 2.6.3 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +95 -0
  4. data/CHANGELOG.md +135 -2
  5. data/Rakefile +13 -7
  6. data/eco-helpers.gemspec +3 -3
  7. data/lib/eco/api/common/loaders/base.rb +2 -2
  8. data/lib/eco/api/common/loaders/case_base.rb +1 -1
  9. data/lib/eco/api/common/loaders/config/workflow/mailer.rb +5 -5
  10. data/lib/eco/api/common/loaders/error_handler.rb +8 -5
  11. data/lib/eco/api/common/loaders/parser.rb +44 -22
  12. data/lib/eco/api/common/loaders/policy.rb +6 -4
  13. data/lib/eco/api/common/loaders/use_case.rb +13 -7
  14. data/lib/eco/api/common/people/base_parser.rb +0 -2
  15. data/lib/eco/api/common/people/default_parsers/boolean_parser.rb +0 -1
  16. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +1 -1
  17. data/lib/eco/api/common/people/default_parsers/date_parser.rb +64 -12
  18. data/lib/eco/api/common/people/default_parsers/freemium_parser.rb +0 -1
  19. data/lib/eco/api/common/people/default_parsers/login_providers_parser.rb +13 -5
  20. data/lib/eco/api/common/people/default_parsers/multi_parser.rb +0 -1
  21. data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +18 -5
  22. data/lib/eco/api/common/people/default_parsers/policy_groups_parser.rb +8 -8
  23. data/lib/eco/api/common/people/default_parsers/select_parser.rb +50 -26
  24. data/lib/eco/api/common/people/default_parsers/send_invites_parser.rb +6 -6
  25. data/lib/eco/api/common/people/default_parsers/xls_parser.rb +9 -12
  26. data/lib/eco/api/common/people/default_parsers.rb +1 -12
  27. data/lib/eco/api/common/people/entries.rb +13 -13
  28. data/lib/eco/api/common/people/entry_factory.rb +76 -45
  29. data/lib/eco/api/common/people/person_attribute_parser.rb +8 -12
  30. data/lib/eco/api/common/people/person_entry.rb +86 -75
  31. data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +60 -44
  32. data/lib/eco/api/common/people/person_factory.rb +30 -22
  33. data/lib/eco/api/common/people/person_modifier.rb +11 -13
  34. data/lib/eco/api/common/people/person_parser.rb +101 -39
  35. data/lib/eco/api/common/people/supervisor_helpers.rb +25 -26
  36. data/lib/eco/api/common/session/base_session.rb +9 -9
  37. data/lib/eco/api/common/session/environment.rb +7 -5
  38. data/lib/eco/api/common/session/sftp.rb +59 -32
  39. data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +10 -6
  40. data/lib/eco/api/common/version_patches/exception.rb +11 -13
  41. data/lib/eco/api/error.rb +32 -20
  42. data/lib/eco/api/microcases/set_supervisor.rb +0 -3
  43. data/lib/eco/api/organization/node_classifications.rb +82 -0
  44. data/lib/eco/api/organization/policy_groups.rb +4 -6
  45. data/lib/eco/api/organization/tag_tree.rb +169 -93
  46. data/lib/eco/api/organization.rb +1 -0
  47. data/lib/eco/api/session/batch/job.rb +1 -1
  48. data/lib/eco/api/session/config/tagtree.rb +41 -23
  49. data/lib/eco/api/session/config/workflow.rb +113 -88
  50. data/lib/eco/api/session/config.rb +6 -0
  51. data/lib/eco/api/session.rb +51 -29
  52. data/lib/eco/api/usecases/base_io.rb +28 -25
  53. data/lib/eco/api/usecases/default/locations/cli/tagtree_extract_cli.rb +7 -2
  54. data/lib/eco/api/usecases/default/locations/cli/tagtree_upload_cli.rb +21 -0
  55. data/lib/eco/api/usecases/default/locations/csv_to_tree_case.rb +3 -3
  56. data/lib/eco/api/usecases/default/locations/tagtree_extract_case.rb +54 -23
  57. data/lib/eco/api/usecases/default/locations/tagtree_upload_case.rb +87 -0
  58. data/lib/eco/api/usecases/default/locations.rb +1 -0
  59. data/lib/eco/api/usecases/default/people/analyse_people_case.rb +60 -56
  60. data/lib/eco/api/usecases/default/people/change_email_case.rb +8 -9
  61. data/lib/eco/api/usecases/default/people/clean_unknown_tags_case.rb +13 -11
  62. data/lib/eco/api/usecases/default/people/clear_abilities_case.rb +2 -2
  63. data/lib/eco/api/usecases/default/people/org_data_convert_case.rb +25 -27
  64. data/lib/eco/api/usecases/default/people/refresh_case.rb +2 -2
  65. data/lib/eco/api/usecases/default/people/reinvite_trans_case.rb +1 -1
  66. data/lib/eco/api/usecases/default/people/reinvite_trans_cli.rb +0 -1
  67. data/lib/eco/api/usecases/default/people/restore_db_case.rb +39 -34
  68. data/lib/eco/api/usecases/default/people/set_default_tag_case.rb +19 -15
  69. data/lib/eco/api/usecases/default/people/supers_cyclic_identify_case.rb +16 -12
  70. data/lib/eco/api/usecases/default_cases/hris_case.rb +17 -15
  71. data/lib/eco/api/usecases/default_cases/samples/sftp_case.rb +30 -16
  72. data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +0 -2
  73. data/lib/eco/api/usecases/graphql/base.rb +5 -3
  74. data/lib/eco/api/usecases/graphql/helpers/base/case_env.rb +4 -1
  75. data/lib/eco/api/usecases/graphql/helpers/base/graphql_env.rb +14 -0
  76. data/lib/eco/api/usecases/graphql/helpers/base.rb +5 -4
  77. data/lib/eco/api/usecases/graphql/helpers/location/base/classifications_parser.rb +60 -0
  78. data/lib/eco/api/usecases/graphql/helpers/location/base/tree_tracking.rb +72 -0
  79. data/lib/eco/api/usecases/graphql/helpers/location/base.rb +25 -59
  80. data/lib/eco/api/usecases/graphql/helpers/location/command/diff/as_update.rb +59 -0
  81. data/lib/eco/api/usecases/graphql/helpers/location/command/diff/compare.rb +49 -0
  82. data/lib/eco/api/usecases/graphql/helpers/location/command/diff.rb +11 -0
  83. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/commandable.rb +46 -0
  84. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable/for_archive.rb +23 -0
  85. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable/for_unarchive.rb +65 -0
  86. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable.rb +49 -0
  87. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/sortable/relation_safe_sort.rb +119 -0
  88. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/sortable.rb +59 -0
  89. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages.rb +82 -0
  90. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs.rb +20 -0
  91. data/lib/eco/api/usecases/graphql/helpers/location/command/optimizations.rb +84 -0
  92. data/lib/eco/api/usecases/graphql/helpers/location/command/result.rb +4 -4
  93. data/lib/eco/api/usecases/graphql/helpers/location/command/results.rb +24 -12
  94. data/lib/eco/api/usecases/graphql/helpers/location/command.rb +21 -24
  95. data/lib/eco/api/usecases/graphql/helpers/location/tags_remap/tags_map.rb +1 -1
  96. data/lib/eco/api/usecases/graphql/helpers/location/tags_remap/tags_set.rb +10 -11
  97. data/lib/eco/api/usecases/graphql/helpers/location/tags_remap.rb +8 -9
  98. data/lib/eco/api/usecases/graphql/samples/location/command/dsl.rb +41 -12
  99. data/lib/eco/api/usecases/graphql/samples/location/command/results.rb +11 -80
  100. data/lib/eco/api/usecases/graphql/samples/location/command/service/tree_update.rb +89 -0
  101. data/lib/eco/api/usecases/graphql/samples/location/command/service.rb +6 -0
  102. data/lib/eco/api/usecases/graphql/samples/location/command/track_changed_ids.rb +89 -0
  103. data/lib/eco/api/usecases/graphql/samples/location/command.rb +3 -0
  104. data/lib/eco/api/usecases/graphql/samples/location/service/base.rb +9 -0
  105. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/heading.rb +18 -0
  106. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/inputable.rb +53 -0
  107. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing/classifications.rb +34 -0
  108. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing/helpers.rb +28 -0
  109. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing.rb +46 -0
  110. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible.rb +38 -0
  111. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff.rb +105 -0
  112. data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/discarded.rb +16 -0
  113. data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/input.rb +15 -0
  114. data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/node_attr_maps.rb +22 -0
  115. data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/parser.rb +45 -0
  116. data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter.rb +36 -0
  117. data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/output.rb +56 -0
  118. data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list.rb +41 -0
  119. data/lib/eco/api/usecases/graphql/samples/location/service.rb +8 -0
  120. data/lib/eco/api/usecases/graphql/samples/location.rb +1 -0
  121. data/lib/eco/api/usecases/graphql/utils/sftp.rb +96 -36
  122. data/lib/eco/api/usecases/ooze_cases/export_register_case.rb +8 -6
  123. data/lib/eco/api/usecases/ooze_samples/helpers/creatable.rb +4 -3
  124. data/lib/eco/api/usecases/ooze_samples/helpers/exportable_ooze.rb +39 -25
  125. data/lib/eco/api/usecases/ooze_samples/helpers/exportable_register.rb +13 -15
  126. data/lib/eco/api/usecases/ooze_samples/helpers/filters.rb +50 -21
  127. data/lib/eco/api/usecases/ooze_samples/helpers/ooze_handlers.rb +21 -11
  128. data/lib/eco/api/usecases/ooze_samples/helpers/rescuable.rb +2 -0
  129. data/lib/eco/api/usecases/ooze_samples/helpers/shortcuts.rb +49 -43
  130. data/lib/eco/api/usecases/ooze_samples/ooze_base_case.rb +17 -19
  131. data/lib/eco/api/usecases/ooze_samples/register_export_case.rb +48 -43
  132. data/lib/eco/api/usecases/ooze_samples/register_update_case.rb +34 -34
  133. data/lib/eco/api/usecases/ooze_samples/target_oozes_update_case.rb +8 -10
  134. data/lib/eco/api/usecases.rb +0 -1
  135. data/lib/eco/cli/config/use_cases.rb +31 -29
  136. data/lib/eco/cli_default/input_filters.rb +0 -5
  137. data/lib/eco/cli_default/people_filters.rb +4 -4
  138. data/lib/eco/cli_default/workflow.rb +13 -14
  139. data/lib/eco/csv/table.rb +34 -25
  140. data/lib/eco/data/hashes/array_diff.rb +24 -35
  141. data/lib/eco/data/hashes/diff_result/meta.rb +131 -0
  142. data/lib/eco/data/hashes/diff_result.rb +65 -57
  143. data/lib/eco/data/hashes/sanke_camel_indifferent_access.rb +278 -0
  144. data/lib/eco/data/hashes.rb +1 -1
  145. data/lib/eco/data/locations/convert.rb +1 -1
  146. data/lib/eco/data/locations/node_base/csv_convert.rb +19 -9
  147. data/lib/eco/data/locations/node_base/parsing.rb +4 -2
  148. data/lib/eco/data/locations/node_base/treeify.rb +149 -132
  149. data/lib/eco/data/locations/node_base.rb +15 -4
  150. data/lib/eco/data/locations/node_diff/accessors.rb +13 -5
  151. data/lib/eco/data/locations/node_diff/nodes_diff/clustered_treeify.rb +101 -0
  152. data/lib/eco/data/locations/node_diff/nodes_diff/diffs_tree.rb +99 -0
  153. data/lib/eco/data/locations/node_diff/{selectors.rb → nodes_diff/selectors.rb} +1 -1
  154. data/lib/eco/data/locations/node_diff/nodes_diff.rb +50 -35
  155. data/lib/eco/data/locations/node_diff.rb +45 -17
  156. data/lib/eco/data/locations/node_level/parsing.rb +15 -21
  157. data/lib/eco/data/locations/node_level.rb +66 -22
  158. data/lib/eco/data/locations/node_plain/parsing.rb +1 -1
  159. data/lib/eco/data/locations/node_plain.rb +60 -7
  160. data/lib/eco/data/strings/camel_case.rb +35 -0
  161. data/lib/eco/data/strings/snake_case.rb +18 -0
  162. data/lib/eco/data/strings.rb +8 -0
  163. data/lib/eco/data.rb +1 -0
  164. data/lib/eco/language/methods/call_detector.rb +11 -0
  165. data/lib/eco/language/methods/dsl_able.rb +7 -1
  166. data/lib/eco/language/methods.rb +2 -1
  167. data/lib/eco/language/models/collection.rb +23 -25
  168. data/lib/eco/language/models/parser_serializer.rb +24 -5
  169. data/lib/eco/version.rb +1 -1
  170. data/lib/eco-helpers.rb +0 -1
  171. metadata +54 -9
  172. data/lib/eco/data/hashes/diff_meta.rb +0 -52
@@ -8,17 +8,16 @@ module Eco
8
8
 
9
9
  include Eco::Language::AuxiliarLogger
10
10
 
11
- attr_reader :source1, :source2
12
- attr_reader :src_h1, :src_h2
13
-
14
- def initialize(source1, source2, logger: nil)
15
- @logger = logger if logger
16
- @source1 = source1
17
- @source2 = source2
18
- @src_h1 = by_key(source1)
19
- @src_h2 = by_key(source2)
20
- raise "Missing source1" unless !!self.src_h1
21
- raise "Missing source2" unless !!self.src_h2
11
+ attr_reader :source_1, :source_2
12
+ attr_reader :src_h_1, :src_h_2
13
+
14
+ def initialize(source_1, source_2, logger: nil)
15
+ @logger = logger if logger
16
+ @source_1 = source_1
17
+ @source_2 = source_2
18
+
19
+ raise "Missing source_1" unless (@src_h_1 = by_key(source_1))
20
+ raise "Missing source_2" unless (@src_h_2 = by_key(source_2))
22
21
  end
23
22
 
24
23
  # @note
@@ -26,35 +25,31 @@ module Eco
26
25
  # - It also allows to know the original value
27
26
  # @return [Hash] where `key` is the key of the record, and `value` a `DiffResult` object
28
27
  def diffs
29
- @diffs ||= source_results.select do |res|
30
- res.diff?
31
- end
28
+ @diffs ||= source_results.select(&:diff?)
32
29
  end
33
30
 
34
31
  # @return [Boolean] wheter or not there are differences.
35
32
  def diffs?
36
- !diffs.empty?
33
+ diffs.any?
37
34
  end
38
35
 
39
36
  # All the items that contain the diff of a node.
40
37
  # @return [Array<Eco::Data::Hash::DiffResult>]
41
38
  def source_results
42
- @source_results ||= paired_sources.each_with_object([]) do |(src1, src2), res|
43
- res << diff_result_class.new(src1, src2)
39
+ @source_results ||= paired_sources.each_with_object([]) do |(src_1, src_2), res|
40
+ res << diff_result_class.new(src_1, src_2)
44
41
  end
45
42
  end
46
43
 
47
44
  protected
48
45
 
49
- # It pairs the hashes of `source1` and `source2`
46
+ # It pairs the hashes of `source_1` and `source_2`
50
47
  # @note
51
48
  # - It also ensures they are in their Hash form (with string keys)
52
49
  # - This will merge entries of the same source that hold the same `key` attr value (latest wins)
53
50
  def paired_sources
54
- keys1 = src_h1.keys
55
- keys2 = src_h2.keys
56
- all_keys = keys1 | keys2
57
- all_keys.map {|key| [src_h1[key], src_h2[key]]}
51
+ all_keys = src_h_1.keys | src_h_2.keys
52
+ all_keys.map {|key| [src_h_1[key], src_h_2[key]]}
58
53
  end
59
54
 
60
55
  # @return [String] the `key` attribute of `diff_result_class`
@@ -68,22 +63,14 @@ module Eco
68
63
  diff_result_class.case_sensitive?
69
64
  end
70
65
 
71
- def compared_attrs
72
- diff_result_class.compared_attrs.map(&:to_s)
73
- end
74
-
75
66
  private
76
67
 
77
68
  def symbolize_keys(hash)
78
- hash.each_with_object({}) do |(k, v), h|
79
- h[k.to_sym] = v
80
- end
69
+ hash.transform_keys(&:to_sym)
81
70
  end
82
71
 
83
72
  def stringify_keys(hash)
84
- hash.each_with_object({}) do |(k, v), h|
85
- h[k.to_s] = v
86
- end
73
+ hash.transform_keys(&:to_s)
87
74
  end
88
75
 
89
76
  def by_key(content)
@@ -95,7 +82,9 @@ module Eco
95
82
  def to_array_of_hashes(content)
96
83
  case content
97
84
  when Hash
98
- logger.error("Input data as 'Hash' not supported. Expecting 'Enumerable' or 'String'")
85
+ log(:error) {
86
+ "(ArrayDiff) Input data as 'Hash' not supported. Expecting 'Enumerable' or 'String'"
87
+ }
99
88
  exit(1)
100
89
  when String
101
90
  to_array_of_hashes(Eco::CSV.parse(content))
@@ -106,13 +95,13 @@ module Eco
106
95
  Eco::CSV::Table.new(content).to_array_of_hashes
107
96
  else
108
97
  log(:error) {
109
- "Input content 'Array' of '#{sample.class}' is not supported."
98
+ "(ArrayDiff) Input content 'Array' of '#{sample.class}' is not supported."
110
99
  }
111
100
  exit(1)
112
101
  end
113
102
  else
114
103
  log(:error) {
115
- "Could not obtain any data out content: '#{content.class}'"
104
+ "(ArrayDiff) Could not obtain any data out content: '#{content.class}'"
116
105
  }
117
106
  exit(1)
118
107
  end
@@ -0,0 +1,131 @@
1
+ module Eco
2
+ module Data
3
+ module Hashes
4
+ class DiffResult
5
+ module Meta
6
+ class << self
7
+ def included(base)
8
+ super(base)
9
+ base.extend Eco::Language::Models::ClassHelpers
10
+ base.extend ClassMethods
11
+ base.inheritable_class_vars :key, :compared_attrs, :case_sensitive
12
+ end
13
+ end
14
+
15
+ module ClassMethods
16
+ # @param value [String, NilClass]
17
+ # @return [String] the attribute that is key of the node diff elements.
18
+ def key(value = nil)
19
+ return @key unless value
20
+ @key = value.to_s
21
+ end
22
+
23
+ # @return [Boolean] is there a `key` attribute defined?
24
+ def key?
25
+ !!@key
26
+ end
27
+
28
+ # @param attrs [Array<Symbol>, Array<String>]
29
+ # @return [Array<String>] the comparable attributes
30
+ def compare(*attrs, when_present: false)
31
+ if when_present
32
+ compared_attrs_when_present.push(*attrs.map(&:to_s)).uniq!
33
+ compared_attrs_when_present
34
+ else
35
+ compared_attrs.push(*attrs.map(&:to_s)).uniq!
36
+ compared_attrs
37
+ end
38
+ end
39
+
40
+ # Whether or not the diff calc of a node should be done case sensitive or insensitive.
41
+ def case_sensitive(value = nil)
42
+ @case_sensitive = false unless instance_variable_defined?(:@case_sensitive)
43
+ return @case_sensitive unless value
44
+ @case_sensitive = !!value
45
+ end
46
+
47
+ # @return [Boolean] are comparisons of values done case sensitive?
48
+ def case_sensitive?
49
+ !!@case_sensitive
50
+ end
51
+
52
+ # @return [Array<String>] the comparable attributes
53
+ def compared_attrs
54
+ @compared_attrs ||= []
55
+ end
56
+
57
+ # Same as `compared_attrs` but they only get compared when present
58
+ # in both data sources
59
+ # @note if present in one source but not in another,
60
+ # that attribute will NOT generate a diff.
61
+ def compared_attrs_when_present
62
+ @compared_attrs_when_present ||= []
63
+ end
64
+
65
+ def all_compared_attrs
66
+ compared_attrs | compared_attrs_when_present
67
+ end
68
+
69
+ def compared_attr_when_present?(attr)
70
+ compared_attrs_when_present.include?(attr)
71
+ end
72
+ end
73
+
74
+ def key
75
+ self.class.key.dup
76
+ end
77
+
78
+ def case_sensitive?
79
+ self.class.case_sensitive?
80
+ end
81
+
82
+ def all_compared_attrs
83
+ self.class.all_compared_attrs.dup.compact.map(&:to_s)
84
+ end
85
+
86
+ private
87
+
88
+ # @return [Boolean] whether `val1` is equal to `val2`
89
+ def eq?(val_1, val_2)
90
+ return eq_ary?(val_1, val_2) if [val_1, val_2].any? {|v| v.is_a?(Array)}
91
+ return true if val_1 == val_2
92
+ return false if case_sensitive?
93
+ return false unless val_2 && val_1
94
+ val_1.upcase == val_2.upcase
95
+ end
96
+
97
+ # Compares two arrays
98
+ # @note
99
+ # 1. Order does NOT matter
100
+ # 2. Repeated elements are treated as one
101
+ def eq_ary?(val_1, val_2)
102
+ return false unless [val_1, val_2].all? {|v| v.is_a?(Array)}
103
+ return true if val_1 == val_2
104
+ v_1 = case_sensitive?? val_1 : val_1.map {|v| v&.upcase}
105
+ v_2 = case_sensitive?? val_2 : val_2.map {|v| v&.upcase}
106
+ joined = (v_1 | v_2)
107
+ (joined & v_1) == (joined & v_2)
108
+ end
109
+
110
+ # Hash access
111
+ # @note DSL to be able to modify behaviour
112
+ # (i.e. indifferent access for camel and snake case keys)
113
+ def get_attr(src, key)
114
+ return nil unless src
115
+ src[key.to_s]
116
+ end
117
+
118
+ def slice_attrs(src, *keys)
119
+ return nil unless src
120
+ src.slice(*keys)
121
+ end
122
+
123
+ def key_present?(src, key)
124
+ return false unless src
125
+ src.key?(key)
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -1,53 +1,68 @@
1
+ require_relative 'diff_result/meta'
2
+
1
3
  module Eco
2
4
  module Data
3
5
  module Hashes
4
6
  class DiffResult
5
- extend Eco::Language::Models::ClassHelpers
6
- include Eco::Data::Hashes::DiffMeta
7
-
8
- inheritable_class_vars :key, :compared_attrs, :case_sensitive
7
+ include Eco::Data::Hashes::DiffResult::Meta
9
8
 
10
- attr_reader :src1, :src2
9
+ attr_reader :src_1, :src_2
11
10
 
12
- def initialize(src1, src2)
13
- @src1 = src1
14
- @src2 = src2
11
+ def initialize(src_1, src_2)
12
+ @src_1 = src_1
13
+ @src_2 = src_2
15
14
  end
16
15
 
17
- def key
18
- self.class.key
16
+ # @return [Value] the current value of `attr` (in `src_2`)
17
+ def attr(attr)
18
+ get_attr(src_2, attr)
19
19
  end
20
20
 
21
- def case_sensitive?
22
- self.class.case_sensitive?
21
+ # @return [Value] the previous value of `attr` (in `src_1`)
22
+ def attr_prev(attr)
23
+ get_attr(src_1, attr)
23
24
  end
24
25
 
25
- def dup(src1: nil, src2: nil)
26
- src1 ||= self.src1
27
- src2 ||= self.src2
28
- self.class.new(src1.dup, src2.dup)
26
+ # Deduplication to prevent mutability when manipulation is required.
27
+ def dup(src_1: nil, src_2: nil)
28
+ src_1 ||= self.src_1
29
+ src_2 ||= self.src_2
30
+ self.class.new(src_1.dup, src_2.dup)
29
31
  end
30
32
 
31
33
  def new?
32
- !src1 && !!src2
34
+ src_2 && !src_1
33
35
  end
34
36
 
35
37
  def del?
36
- !!src1 && !src2
38
+ src_1 && !src_2
37
39
  end
38
40
 
39
41
  def update?
40
42
  !new? && !del? && diff?
41
43
  end
42
44
 
45
+ # Uniq access point to identify attrs that have changed.
46
+ # @note when is `new?` or to be deleted (`del?`), there's nothing to compare.
47
+ # @return [Array<Symbol>] hash with the list of attrs that are different
48
+ # between `src_1` and `src_2`.
49
+ def diff_attrs
50
+ return (@diff_attrs = []) if new? || del?
51
+ @diff_attrs ||= all_compared_attrs.each_with_object([]) do |kattr, out|
52
+ next unless comparable_attr?(kattr)
53
+ out << kattr unless eq?(attr_prev(kattr), attr(kattr))
54
+ end
55
+ end
56
+
43
57
  # @note `diff_attrs` may not include the `key` attribute
44
58
  # This is always included via `new?` (new key value) and `del?` (missing key value)
45
59
  # @return [Boolean] was there any change?
46
60
  def diff?
47
- new? || del? || !diff_attrs.empty?
61
+ new? || del? || diff_attrs.any?
48
62
  end
49
63
 
50
- # Is the `key` attr value changing?
64
+ # Is the `key` attr value updated?
65
+ # @note that `new?` and `del?` won't be considered as key's change
51
66
  def key?
52
67
  !(new? || del?) && diff_attr?(key)
53
68
  end
@@ -59,54 +74,47 @@ module Eco
59
74
  diff_attrs.include?(attr.to_s)
60
75
  end
61
76
 
62
- # @return [Value] the current value of `attr` (in `src2`)
63
- def attr(attr)
64
- return nil unless src2
65
- src2[attr.to_s]
66
- end
67
-
68
- # @return [Value] the previous value of `attr` (in `src1`)
69
- def attr_prev(attr)
70
- return nil unless src1
71
- src1[attr.to_s]
72
- end
73
-
74
77
  # @note the `key` attribute will always be added (even if there's no change)
75
- # @return [Hash] hash with the differences as per `src2`
78
+ # @return [Hash] hash with the differences as per `src_2`
76
79
  def diff_hash
77
- target_attrs = [key] | compared_attrs
78
- return src2.slice(*target_attrs) if new?
79
- return src1.slice(key) if del?
80
- src2.slice(key, *diff_attrs)
80
+ target_attrs = [key] | all_compared_attrs
81
+ return slice_attrs(src_2, *target_attrs) if new?
82
+ return slice_attrs(src_1, key) if del?
83
+ slice_attrs(src_2, key, *diff_attrs)
81
84
  end
82
85
 
83
- # @return [Array<Symbol>] hash with the differences as per `src2`
84
- def diff_attrs
85
- @diff_attrs ||= comparable_attrs.each_with_object([]) do |attr, out|
86
- out << attr unless eq?(src1[attr], src2[attr])
86
+ # Uniq access point to scope if an `attr` is in the scope of the diff compare.
87
+ # Set of attributes that are general target to identify differences
88
+ # between both sources.
89
+ # @note When the class `all_compared_attrs` has not been deefined,
90
+ # it uses `all_source_keys`
91
+ # @return [Array<String>] the set of attributes that are comparable in this class.
92
+ def all_compared_attrs
93
+ super().map(&:to_s).uniq.tap do |attrs|
94
+ return all_source_keys unless attrs.any?
87
95
  end
88
96
  end
89
97
 
90
- # @return [Boolean] whether `val1` is equal to `val2`
91
- def eq?(val1, val2)
92
- return true if val1 == val2
93
- return false if case_sensitive?
94
- return false if !val2 || !val1
95
- val1.upcase == val2.upcase
98
+ # All the keys that the data comes with
99
+ def all_source_keys
100
+ (src_1&.keys || []) & (src_2&.keys || [])
96
101
  end
97
102
 
98
- # @note when is `new?` or to be deleted (`del?`), it returns empty array.
99
- # @return [Array<String>] the set of attributes that are comparable in this instance.
100
- def comparable_attrs
101
- return [] if new? || del?
102
- compared_attrs
103
+ private
104
+
105
+ # Refinement over `all_compared_attrs`, provided that those that must
106
+ # be comparable only **when present** in both, are filtered out when
107
+ # that is not the case.
108
+ def comparable_attr?(attr)
109
+ attr = attr.to_s
110
+ return false unless all_compared_attrs.include?(attr)
111
+ return true unless self.class.compared_attr_when_present?(attr)
112
+ key_present_in_both?(attr)
103
113
  end
104
114
 
105
- # @return [Array<String>] the set of attributes that are comparable in this class.
106
- def compared_attrs
107
- comp_attrs = self.class.compared_attrs.map(&:to_s).uniq
108
- return comp_attrs unless comp_attrs.empty?
109
- (src1&.keys || []) & (src2&.keys || [])
115
+ # Is the key `attr` present in both sources?
116
+ def key_present_in_both?(attr)
117
+ key_present?(src_1, attr) && key_present?(src_2, attr)
110
118
  end
111
119
  end
112
120
  end