eco-helpers 3.2.4 → 3.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec05b98fd01a73712e5db28ef750583f57d96438f30a2e4e58fc531d007802e1
4
- data.tar.gz: c1071fd1909830cfbb72838f9051234f9268a5bafa6e6b970a80790c05ef1ad5
3
+ metadata.gz: 8bb545e3154c1a65a993a24b6eeab4eebbe125e95492bc2b6961fee0a708a80f
4
+ data.tar.gz: dc6bd380cd757b5218fadf264c64ef8a61b767916514aebac63fae0739c5153c
5
5
  SHA512:
6
- metadata.gz: 779aa495731d5e3abcb145c983c6a8271e9d4a41fb939f4a63dda4735b08b0dfc7fd2df1fcafbfade6e65651fa3af24c27b94cf18ea6977d752ef8c36abbb1da
7
- data.tar.gz: edc3abd001e262f4ed9bab3867bcd9e8f4d9de108ae58b8a16f581bf054e546908c175d1bd24f8541977f65b44972226cae0b1b58ef20ad112cb2b90af591c1c
6
+ metadata.gz: b9852caf3f9f2dcdcbcbe4d17e325c566e63b3724b92349668e35fb4839aea5b7879b3b080b031868495b40c5bb09a9fc9d43c0b5cd4e9dbc298ec0f25d867d8
7
+ data.tar.gz: 5941ec298de1bff8205be578bcefaed0602dfea76ceee47a00497b28ff973a293553927d1ce96f0617abe0886c5fa4f5810678e69c3fab2673fd35c6df88dac3
data/CHANGELOG.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [3.2.5] - 2025-08-xx
5
+ ## [3.2.7] - 2025-09-xx
6
6
 
7
7
  ### Added
8
8
 
@@ -10,6 +10,39 @@ All notable changes to this project will be documented in this file.
10
10
 
11
11
  ### Fixed
12
12
 
13
+ ## [3.2.6] - 2025-09-05
14
+
15
+ ### Added
16
+
17
+ - **Improvement**: classifications conversion to ignore ending `s` (plurals).
18
+
19
+ ### Fixed
20
+
21
+ - Node `id` and `parent_id` **upcase** in `NodePlain` (**case insensitive**)
22
+ - It was failing to pair children with their parent (on input files).
23
+ - **remove** _classifications treatment_ on `Organization::TagTree` and `NodePlain`
24
+ - This was a working around due to not using `as_nodes_json` as a **common** converter between `live_tree` and `file_tree` (which was fixed in a previous release).
25
+ - `as_nodes_json` already does the call to `node_parser_block`, which does the conversion of the **classifications**
26
+
27
+ ## [3.2.6] - 2025-09-xx
28
+
29
+ ### Added
30
+
31
+ ### Changed
32
+
33
+ ### Fixed
34
+
35
+ ## [3.2.5] - 2025-09-04
36
+
37
+ ### Changed
38
+
39
+ - `ArrayDiff`: allow empty array but give **warning**.
40
+
41
+ ### Fixed
42
+
43
+ - upgrade `ecoportal-api-graphql` **gem**.
44
+ - Fixed **tree tracking** on dry-run mode.
45
+
13
46
  ## [3.2.4] - 2025-08-26
14
47
 
15
48
  ### Fixed
data/eco-helpers.gemspec CHANGED
@@ -42,7 +42,7 @@ Gem::Specification.new do |spec|
42
42
  spec.add_dependency 'docx', '>= 0.8.0', '< 0.9'
43
43
  spec.add_dependency 'dotenv', '~> 3'
44
44
  spec.add_dependency 'ecoportal-api', '~> 0.10', '>= 0.10.14'
45
- spec.add_dependency 'ecoportal-api-graphql', '~> 1.3', '>= 1.3.3'
45
+ spec.add_dependency 'ecoportal-api-graphql', '~> 1.3', '>= 1.3.4'
46
46
  spec.add_dependency 'ecoportal-api-v2', '~> 3.3', '>= 3.3.1'
47
47
  spec.add_dependency 'ed25519', '~> 1.2'
48
48
  spec.add_dependency 'fast_excel', '>= 0.5.0', '< 0.6'
@@ -66,10 +66,11 @@ module Eco
66
66
  treat_classication(val)
67
67
  end
68
68
 
69
+ # Enhances the lookup
69
70
  def treat_classication(value)
70
71
  return value unless value.is_a?(String)
71
72
 
72
- value.strip.gsub(/\W+/, '').downcase
73
+ value.strip.downcase.gsub(/s(?:\W|$)/, '').gsub(/\W+/, '-')
73
74
  end
74
75
 
75
76
  def init_caches
@@ -211,9 +211,9 @@ module Eco
211
211
  &block
212
212
  )
213
213
  max_depth ||= total_depth
214
- return nil if max_depth < depth
215
- return [] if top? && !include_children
216
- return nil if archived? && !include_archived
214
+ return if max_depth < depth
215
+ return [] if top? && !include_children
216
+ return if archived? && !include_archived
217
217
 
218
218
  if include_children
219
219
  child_nodes = nodes
@@ -441,14 +441,13 @@ module Eco
441
441
 
442
442
  def init_node
443
443
  return if source.is_a?(Array)
444
+
444
445
  @id = source.values_at('tag', 'id').compact.first&.upcase
445
446
  @name = source['name']
446
447
  @weight = source['weight']
447
448
  @archived = as_boolean(source['archived'])
448
449
  @archived_token = source['archived_token']
449
- @classifications = into_a(source['classifications']).map do |value|
450
- treat_classication(value)
451
- end
450
+ @classifications = into_a(source['classifications'])
452
451
  @classification_names = into_a(source['classification_names'])
453
452
  @raw_nodes = source['nodes'] || []
454
453
  end
@@ -491,11 +490,6 @@ module Eco
491
490
  [tnodes, ddepth]
492
491
  end
493
492
 
494
- def treat_classication(value)
495
- return value unless value.is_a?(String)
496
- value.strip.gsub(/\W+/, '').downcase
497
- end
498
-
499
493
  # Helper to convert to array
500
494
  def into_a(value)
501
495
  if value.is_a?(String)
@@ -510,6 +504,7 @@ module Eco
510
504
  return true if value == true
511
505
  return false if value.to_s.strip.empty?
512
506
  return true if %w[yes x true].include?(value.downcase)
507
+
513
508
  false
514
509
  end
515
510
  end
@@ -40,7 +40,7 @@ class Eco::API::UseCases::Default::Locations::TagtreeExtract < Eco::API::UseCase
40
40
  msg << " #{FORMATS.join(', ')}"
41
41
  msg << ". \nAborting..."
42
42
 
43
- log(:error) { msg }
43
+ log(:error) { msg }
44
44
  exit 1
45
45
  end
46
46
  end
@@ -112,6 +112,11 @@ class Eco::API::UseCases::Default::Locations::TagtreeExtract < Eco::API::UseCase
112
112
  end]
113
113
  else
114
114
  retrieve_live_trees
115
+ end.tap do |trees|
116
+ next if trees.any?
117
+
118
+ log(:warn) { 'No live trees with nodes found. Aborting...' }
119
+ exit 1
115
120
  end
116
121
  end
117
122
 
@@ -5,39 +5,46 @@ module Eco::API::UseCases::GraphQL::Helpers::Location
5
5
 
6
6
  private
7
7
 
8
+ def to_classification_ids(values)
9
+ values = [values].flatten unless values.is_a?(Array)
10
+
11
+ values = values.compact.map {|val| val.split('|')}.flatten
12
+ values.compact.map {|val| to_classification(val)}.compact.uniq
13
+ end
14
+
8
15
  # @note
9
16
  # 1. It returns `nil` unless there are classifications defined
10
17
  # 2. If the value is wrong, it warns and returns `nil`
11
18
  def to_classification(value)
12
- return nil unless node_classifications?
19
+ return unless node_classifications?
13
20
 
14
- raise ArgumentError, "Expecting a single element. Given: #{value.class}" if value.is_a?(Enumerator)
21
+ msg = "Expecting a single element. Given: #{value.class}"
22
+ raise ArgumentError, msg if value.is_a?(Enumerator)
15
23
 
16
- return nil unless value.is_a?(String)
24
+ return unless value.is_a?(String)
17
25
 
18
26
  node_classifications.to_id(value).tap do |type|
19
- unknown_clasification!(value) unless type
20
- end
21
- end
27
+ next if type
22
28
 
23
- def to_classification_ids(values)
24
- values = [values].flatten unless values.is_a?(Array)
25
- values = values.compact.map {|val| val.split('|')}.flatten
26
- values.compact.map {|val| to_classification(val)}.compact.uniq
29
+ unknown_classification!(value)
30
+ end
27
31
  end
28
32
 
29
33
  # @note
30
34
  # 1. It returns `nil` unless there are classifications defined
31
35
  # 2. If the value is wrong, it warns and returns `nil`
32
36
  def to_classification_name(value)
33
- return nil unless node_classifications?
37
+ return unless node_classifications?
34
38
 
35
- raise ArgumentError, "Expecting a single element. Given: #{value.class}" if value.is_a?(Enumerator)
39
+ msg = "Expecting a single element. Given: #{value.class}"
40
+ raise ArgumentError, msg if value.is_a?(Enumerator)
36
41
 
37
- return nil unless value.is_a?(String)
42
+ return unless value.is_a?(String)
38
43
 
39
44
  node_classifications.to_name(value) do |name|
40
- unknown_clasification!(value) unless name
45
+ next unless name
46
+
47
+ unknown_classification!(value)
41
48
  end
42
49
  end
43
50
 
@@ -49,10 +56,11 @@ module Eco::API::UseCases::GraphQL::Helpers::Location
49
56
  @node_classifications ||= session.node_classifications
50
57
  end
51
58
 
52
- def unknown_clasification!(value)
59
+ def unknown_classification!(value)
53
60
  return if unknown_classifications.include?(value)
54
61
 
55
62
  unknown_classifications << value
63
+
56
64
  log(:warn) {
57
65
  "Unknown location node classification '#{value}'"
58
66
  }
@@ -23,15 +23,17 @@ module Eco::API::UseCases::GraphQL::Helpers::Location
23
23
 
24
24
  @previous_tree = @current_tree
25
25
  @current_tree = value
26
+
27
+ return unless track_current_tree?
28
+ return if simulate?
29
+
26
30
  backup_tree(current_tree)
27
31
  end
28
32
 
29
33
  # At any moment we want to know how the live tree is
30
34
  # @note it also does a backup
31
35
  # @return [Eco::API::Organization::TagTree] the latest tree (`current_tree`)
32
- def track_current_tree(tree) # rubocop:disable Metrics/AbcSize
33
- return unless track_current_tree?
34
- return if simulate?
36
+ def track_current_tree(tree)
35
37
  return if tree.nil?
36
38
 
37
39
  tree_id = current_tree&.id
@@ -3,6 +3,7 @@ module Eco
3
3
  module Hashes
4
4
  class ArrayDiff
5
5
  extend Eco::Language::Klass::HelpersBuilt
6
+
6
7
  # We can change the `DiffResult` class (items)
7
8
  class_resolver :diff_result_class, "Eco::Data::Hash::DiffResult"
8
9
 
@@ -104,16 +105,18 @@ module Eco
104
105
  Eco::CSV::Table.new(content).to_array_of_hashes
105
106
  else
106
107
  if content_cnt.zero?
107
- log(:error) {
108
- "Inpout should not be empty"
108
+ log(:warning) {
109
+ '(ArrayDiff) Got empty array !!!'
109
110
  }
111
+
112
+ []
110
113
  else
111
114
  log(:error) {
112
115
  "(ArrayDiff) Input content 'Array' of '#{sample.class}' is not supported."
113
116
  }
114
- end
115
117
 
116
- exit(1)
118
+ exit(1)
119
+ end
117
120
  end
118
121
  else
119
122
  log(:error) {
@@ -2,7 +2,7 @@ module Eco::Data::Locations::NodeBase
2
2
  module TagValidations
3
3
  include Eco::Language::AuxiliarLogger
4
4
 
5
- ALLOWED_CHARACTERS = "A-Za-z0-9 &_'\/.-".freeze
5
+ ALLOWED_CHARACTERS = "A-Za-z0-9 &_'/.-".freeze
6
6
  VALID_TAG_REGEX = /^[#{ALLOWED_CHARACTERS}]+$/
7
7
  INVALID_TAG_REGEX = /[^#{ALLOWED_CHARACTERS}]+/
8
8
  VALID_TAG_CHARS = /[#{ALLOWED_CHARACTERS}]+/
@@ -11,9 +11,11 @@ module Eco::Data::Locations::NodeBase
11
11
  def clean_id(str, notify: true, ref: '')
12
12
  blanks_x2 = has_double_blanks?(str) # dubocop:disable Naming/VariableNumber
13
13
  partial = replace_not_allowed(str)
14
+
14
15
  remove_double_blanks(partial).tap do |result|
15
16
  next unless notify
16
17
  next if invalid_warned?(str)
18
+
17
19
  if partial != str
18
20
  invalid_chars = identify_invalid_characters(str)
19
21
  log(:warn) {
@@ -24,6 +26,7 @@ module Eco::Data::Locations::NodeBase
24
26
  "* #{ref}Double blanks removed: '#{str}' :_converted_>> '#{result}'"
25
27
  }
26
28
  end
29
+
27
30
  invalid_warned!(str)
28
31
  end
29
32
  end
@@ -46,13 +49,15 @@ module Eco::Data::Locations::NodeBase
46
49
  end
47
50
 
48
51
  def remove_double_blanks(str)
49
- return nil if str.nil?
52
+ return if str.nil?
53
+
50
54
  str.gsub(DOUBLE_BLANKS, ' ').strip
51
55
  end
52
56
 
53
57
  def replace_not_allowed(str)
54
- return nil if str.nil?
58
+ return if str.nil?
55
59
  return str if str.match(VALID_TAG_REGEX)
60
+
56
61
  str.gsub(INVALID_TAG_REGEX, ' ')
57
62
  end
58
63
 
@@ -28,10 +28,12 @@ module Eco::Data::Locations::NodeBase
28
28
  # @return [Array<Hash>] a hierarchical tree of nested Hashes via `nodes` key.
29
29
  def treeify(nodes, skipped: [], unlinked_trees: [], &block)
30
30
  return [] if nodes.empty?
31
+
31
32
  block ||= nodes.first.class.serializer
32
33
  done_ids = {}
33
34
  warns = []
34
35
  parents = parents_hash(nodes)
36
+
35
37
  get_children(
36
38
  nil, parents,
37
39
  done_ids: done_ids, skipped: skipped,
@@ -43,6 +45,7 @@ module Eco::Data::Locations::NodeBase
43
45
  skipped: skipped, unlinked_trees: unlinked_trees,
44
46
  warns: warns, &block
45
47
  )
48
+
46
49
  log(:warn) { warns.join("\n") } unless warns.empty?
47
50
  end
48
51
  end
@@ -23,7 +23,7 @@ module Eco::Data::Locations
23
23
  end
24
24
 
25
25
  def attr?(sym)
26
- !attr(sym).to_s.strip.empty?
26
+ !attr(sym).to_s.strip.empty? # rubocop:disable Style/Attr
27
27
  end
28
28
 
29
29
  def set_attrs(**kargs)
@@ -57,6 +57,7 @@ module Eco::Data::Locations
57
57
 
58
58
  def slice(*attrs)
59
59
  return {} if attrs.empty?
60
+
60
61
  to_h(*attrs)
61
62
  end
62
63
  end
@@ -17,6 +17,7 @@ class Eco::Data::Locations::NodeLevel
17
17
  # @return [Boolean] whether or not it's worthy trying to parse with `NodeLevel`.
18
18
  def csv_matches_format?(csv)
19
19
  return false unless csv.is_a?(::CSV::Table)
20
+
20
21
  !Eco::Data::Locations::NodePlain.csv_matches_format?(csv)
21
22
  end
22
23
 
@@ -26,7 +27,8 @@ class Eco::Data::Locations::NodeLevel
26
27
  # @param `csv` [CSV::Table]
27
28
  # @return [Array<NodeLevel>]
28
29
  def nodes_from_csv(csv)
29
- raise ArgumentError, "Expecting CSV::Table. Given: #{csv.class}" unless csv.is_a?(::CSV::Table)
30
+ msg = "Expecting CSV::Table. Given: #{csv.class}"
31
+ raise ArgumentError, msg unless csv.is_a?(::CSV::Table)
30
32
 
31
33
  possible_classifications = csv.headers
32
34
 
@@ -52,6 +54,7 @@ class Eco::Data::Locations::NodeLevel
52
54
 
53
55
  prev_node = node
54
56
  end
57
+
55
58
  tidy_nodes(nodes)
56
59
  end
57
60
  end
@@ -36,15 +36,19 @@ module Eco::Data::Locations
36
36
  end
37
37
 
38
38
  # In node level the parent id is set via parsing
39
- attr_accessor :parentId # rubocop:disable Naming/MethodName
40
- alias_method :parent_id=, :parentId=
41
- alias_method :parent_id, :parentId
39
+ attr_writer :parent_id
40
+ alias_method :parentId=, :parent_id= # rubocop:disable Naming/MethodName
41
+
42
+ def parent_id
43
+ @parent_id&.upcase
44
+ end
45
+ alias_method :parentId, :parent_id # rubocop:disable Naming/MethodName
42
46
 
43
47
  def id
44
48
  tag.upcase
45
49
  end
46
- alias_method :nodeId, :id
47
- alias_method :node_id, :nodeId
50
+ alias_method :node_id, :id
51
+ alias_method :nodeId, :id # rubocop:disable Naming/MethodName
48
52
 
49
53
  def name
50
54
  tag
@@ -16,6 +16,7 @@ class Eco::Data::Locations::NodePlain
16
16
  # @return [Boolean] whether or not it's worthy trying to parse with `NodePlain`.
17
17
  def csv_matches_format?(csv)
18
18
  return false unless csv.is_a?(::CSV::Table)
19
+
19
20
  (basic_headers & csv.headers) == basic_headers
20
21
  end
21
22
 
@@ -23,7 +24,9 @@ class Eco::Data::Locations::NodePlain
23
24
  # @param `csv` [CSV::Table] with specific headers
24
25
  # @return [Array<NodePlain>]
25
26
  def nodes_from_csv(csv)
26
- raise ArgumentError, "Expecting CSV::Table. Given: #{csv.class}" unless csv.is_a?(::CSV::Table)
27
+ msg = "Expecting CSV::Table. Given: #{csv.class}"
28
+ raise ArgumentError, msg unless csv.is_a?(::CSV::Table)
29
+
27
30
  # Convert to Eco::CSV::Table for a fresh start
28
31
  csv = Eco::CSV.parse(csv.to_csv).nil_blank_cells.add_index_column(:row_num)
29
32
  headers = node_class::ALL_ATTRS.map(&:to_s)
@@ -22,7 +22,10 @@ module Eco::Data::Locations
22
22
  PROP_ATTRS = (ALL_ATTRS - ADDITIONAL_ATTRS).freeze
23
23
 
24
24
  def id
25
- clean_id(super, ref: "(Row: #{row_num}) ")
25
+ clean_id(
26
+ super,
27
+ ref: "(Row: #{row_num}) "
28
+ )&.upcase
26
29
  end
27
30
  # backwards compatibility
28
31
  alias_method :tag, :id
@@ -32,9 +35,13 @@ module Eco::Data::Locations
32
35
  end
33
36
 
34
37
  def parent_id
35
- clean_id(super, notify: false, ref: "(Row: #{row_num} - parent_id) ")
38
+ clean_id(
39
+ super,
40
+ notify: false,
41
+ ref: "(Row: #{row_num} - parent_id) "
42
+ )&.upcase
36
43
  end
37
- alias_method :parentId, :parent_id
44
+ alias_method :parentId, :parent_id # rubocop:disable Naming/MethodName
38
45
 
39
46
  def archived
40
47
  value = super
@@ -42,13 +49,12 @@ module Eco::Data::Locations
42
49
  return true if value == true
43
50
  return false if value.to_s.strip.empty?
44
51
  return true if %w[yes x true].include?(value.downcase)
52
+
45
53
  false
46
54
  end
47
55
 
48
56
  def classifications
49
- into_a(super).map do |value|
50
- treat_classication(value)
51
- end
57
+ into_a(super)
52
58
  end
53
59
 
54
60
  def classification_names
@@ -68,11 +74,6 @@ module Eco::Data::Locations
68
74
 
69
75
  private
70
76
 
71
- def treat_classication(value)
72
- return value unless value.is_a?(String)
73
- value.strip.gsub(/\W+/, '').downcase
74
- end
75
-
76
77
  # Helper to convert to array
77
78
  def into_a(value)
78
79
  if value.is_a?(String)
data/lib/eco/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eco
2
- VERSION = '3.2.4'.freeze
2
+ VERSION = '3.2.6'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eco-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.4
4
+ version: 3.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Segura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-08-28 00:00:00.000000000 Z
11
+ date: 2025-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: byebug
@@ -263,7 +263,7 @@ dependencies:
263
263
  version: '1.3'
264
264
  - - ">="
265
265
  - !ruby/object:Gem::Version
266
- version: 1.3.3
266
+ version: 1.3.4
267
267
  type: :runtime
268
268
  prerelease: false
269
269
  version_requirements: !ruby/object:Gem::Requirement
@@ -273,7 +273,7 @@ dependencies:
273
273
  version: '1.3'
274
274
  - - ">="
275
275
  - !ruby/object:Gem::Version
276
- version: 1.3.3
276
+ version: 1.3.4
277
277
  - !ruby/object:Gem::Dependency
278
278
  name: ecoportal-api-v2
279
279
  requirement: !ruby/object:Gem::Requirement