eco-helpers 3.0.18 → 3.0.20

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +34 -3
  4. data/eco-helpers.gemspec +3 -3
  5. data/lib/eco/api/common/loaders/config/session.rb +12 -0
  6. data/lib/eco/api/common/loaders/config/workflow/mailer.rb +17 -4
  7. data/lib/eco/api/common/loaders/config.rb +10 -2
  8. data/lib/eco/api/common/loaders/parser.rb +10 -0
  9. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +21 -208
  10. data/lib/eco/api/common/people/default_parsers/helpers/expected_headers.rb +206 -0
  11. data/lib/eco/api/common/people/default_parsers/helpers/null_parsing.rb +36 -0
  12. data/lib/eco/api/common/people/default_parsers/helpers.rb +15 -0
  13. data/lib/eco/api/common/people/default_parsers/json_parser.rb +56 -0
  14. data/lib/eco/api/common/people/default_parsers/xls_parser.rb +13 -14
  15. data/lib/eco/api/common/people/default_parsers.rb +2 -0
  16. data/lib/eco/api/common/people/entry_factory.rb +15 -4
  17. data/lib/eco/api/common/session/sftp.rb +5 -0
  18. data/lib/eco/api/custom/mailer.rb +1 -0
  19. data/lib/eco/api/error.rb +4 -0
  20. data/lib/eco/api/session/batch/job.rb +14 -16
  21. data/lib/eco/api/session/batch/jobs.rb +6 -8
  22. data/lib/eco/api/session/batch/launcher/mode_size.rb +5 -2
  23. data/lib/eco/api/session/batch/launcher/retry.rb +6 -1
  24. data/lib/eco/api/session/batch/launcher/status_handling.rb +4 -2
  25. data/lib/eco/api/session/batch/launcher.rb +3 -3
  26. data/lib/eco/api/session/config/api.rb +1 -0
  27. data/lib/eco/api/session/config/apis/one_off.rb +6 -6
  28. data/lib/eco/api/session/config/workflow.rb +16 -3
  29. data/lib/eco/api/session.rb +13 -7
  30. data/lib/eco/api/usecases/default/locations/tagtree_extract_case.rb +1 -0
  31. data/lib/eco/api/usecases/default/locations/tagtree_upload_case.rb +2 -0
  32. data/lib/eco/api/usecases/default/utils/cli/group_csv_cli.rb +26 -0
  33. data/lib/eco/api/usecases/default/utils/cli/json_to_csv_cli.rb +10 -0
  34. data/lib/eco/api/usecases/default/utils/cli/sort_csv_cli.rb +17 -0
  35. data/lib/eco/api/usecases/default/utils/cli/split_json_cli.rb +15 -0
  36. data/lib/eco/api/usecases/default/utils/group_csv_case.rb +213 -0
  37. data/lib/eco/api/usecases/default/utils/json_to_csv_case.rb +71 -0
  38. data/lib/eco/api/usecases/default/utils/sort_csv_case.rb +127 -0
  39. data/lib/eco/api/usecases/default/utils/split_json_case.rb +224 -0
  40. data/lib/eco/api/usecases/default/utils.rb +4 -0
  41. data/lib/eco/api/usecases/default_cases/samples/sftp_case.rb +22 -15
  42. data/lib/eco/api/usecases/ooze_cases/export_register_case.rb +6 -6
  43. data/lib/eco/api/usecases/ooze_samples/helpers/exportable_register.rb +1 -0
  44. data/lib/eco/api/usecases/ooze_samples/ooze_base_case.rb +1 -1
  45. data/lib/eco/api/usecases/ooze_samples/ooze_run_base_case.rb +8 -5
  46. data/lib/eco/cli_default/workflow.rb +10 -4
  47. data/lib/eco/csv/stream.rb +2 -0
  48. data/lib/eco/csv.rb +3 -2
  49. data/lib/eco/language/methods/delegate_missing.rb +4 -3
  50. data/lib/eco/version.rb +1 -1
  51. metadata +22 -9
@@ -0,0 +1,127 @@
1
+ class Eco::API::UseCases::Default::Utils::SortCsv < Eco::API::Custom::UseCase
2
+ name 'sort-csv'
3
+ type :other
4
+
5
+ require_relative 'cli/sort_csv_cli'
6
+
7
+ def main(*_args)
8
+ if simulate?
9
+ count = Eco::CSV.count(input_file)
10
+ log(:info) { "CSV '#{input_file}' has #{count} rows." }
11
+ else
12
+ group_input_rows
13
+ generate_file
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :headers, :headers_rest
20
+
21
+ def group_input_rows
22
+ idx = 0
23
+ first = true
24
+
25
+ Eco::CSV.foreach(input_file, headers: true, skip_blanks: true) do |row|
26
+ idx += 1
27
+
28
+ if first
29
+ first = false
30
+ @output_headers = row.headers
31
+ require_sort_field!(row, file: input_file)
32
+ end
33
+
34
+ pivot_value = row[sort_field]
35
+ (row_groups[pivot_value] ||= []) << row
36
+
37
+ if (idx % 500).zero?
38
+ print "... Tracked #{idx} rows \r"
39
+ $stdout.flush
40
+ end
41
+ end
42
+ ensure
43
+ log(:info) { "Tracked #{idx} rows"}
44
+ end
45
+
46
+ def generate_file
47
+ idx = 0
48
+
49
+ CSV.open(output_filename, 'wb') do |csv|
50
+ csv << @output_headers
51
+
52
+ row_groups.keys.sort.each do |key|
53
+ row_groups[key].each do |row|
54
+ csv << row.values_at(*@output_headers)
55
+
56
+ idx += 1
57
+ if (idx % 500).zero?
58
+ print "... Sorted #{idx} rows \r"
59
+ $stdout.flush
60
+ end
61
+ end
62
+ end
63
+ end
64
+ ensure
65
+ msg = "Generated file '#{output_filename}' with #{idx} rows."
66
+ log(:info) { msg } unless simulate?
67
+ end
68
+
69
+ def row_groups
70
+ @row_groups ||= {}
71
+ end
72
+
73
+ def output_filename
74
+ return nil unless input_name
75
+
76
+ File.join(input_dir, "#{input_name}_sorted#{input_ext}")
77
+ end
78
+
79
+ def input_name
80
+ @input_name ||= File.basename(input_basename, input_ext)
81
+ end
82
+
83
+ def input_ext
84
+ @input_ext ||= input_basename.split('.')[1..].join('.').then do |name|
85
+ ".#{name}"
86
+ end
87
+ end
88
+
89
+ def input_basename
90
+ @input_basename ||= File.basename(input_full_filename)
91
+ end
92
+
93
+ def input_dir
94
+ @input_dir = File.dirname(input_full_filename)
95
+ end
96
+
97
+ def input_full_filename
98
+ @input_full_filename ||= File.expand_path(input_file)
99
+ end
100
+
101
+ def input_file
102
+ options.dig(:input, :file)
103
+ end
104
+
105
+ def require_sort_field!(row, file:)
106
+ return true if row.key?(sort_field)
107
+
108
+ msg = "Sort field '#{sort_field}' missing in header of file '#{file}'"
109
+ log(:error) { msg }
110
+ raise msg
111
+ end
112
+
113
+ def sort_field
114
+ @sort_field ||= opts_sort_by.tap do |pivot|
115
+ next if pivot
116
+
117
+ msg = "The pivot field should be specified with -by option"
118
+
119
+ log(:error) { msg }
120
+ raise msg
121
+ end
122
+ end
123
+
124
+ def opts_sort_by
125
+ options.dig(:input, :sort_by)
126
+ end
127
+ end
@@ -0,0 +1,224 @@
1
+ class Eco::API::UseCases::Default::Utils::SplitJson < Eco::API::Common::Loaders::UseCase
2
+ require_relative 'cli/split_json_cli'
3
+
4
+ MAX_ITEMS = 15_000
5
+
6
+ name "split-json"
7
+ type :other
8
+
9
+ def main(*_args)
10
+ if simulate?
11
+ count = input_json.count
12
+ log(:info) { "JSON '#{input_file}' has #{count} elements." }
13
+ else
14
+ split_json_into_files!
15
+
16
+ msg = []
17
+ msg << "Total elements: #{total_count}"
18
+ msg << "Generated files:"
19
+ out_files.each do |file|
20
+ msg << " * #{file}'"
21
+ end
22
+
23
+ log(:info) { msg.join("\n") }
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def split_json_into_files!
30
+ first = true
31
+
32
+ while pending?
33
+ swap_file! if first
34
+ first = false
35
+
36
+ curr_json << input_json.shift
37
+ next_count!
38
+
39
+ swap_file! if split?
40
+ end
41
+
42
+ generate_file!
43
+ end
44
+
45
+ def split?
46
+ return false unless curr_count > max_items
47
+
48
+ true
49
+ end
50
+
51
+ def max_items
52
+ @max_items ||= max_items_options || self.class::MAX_ITEMS
53
+ end
54
+
55
+
56
+ # OPTIONS
57
+
58
+ def max_items_options
59
+ return unless (num = options.dig(:output, :file, :max_items))
60
+
61
+ num = num.to_i
62
+ num = nil if num.zero?
63
+ num
64
+ end
65
+
66
+ # OUTPUT JSON
67
+
68
+ # Returns the last json array and blanks the variable
69
+ def exporting_json!
70
+ curr_json.tap do
71
+ @curr_json = []
72
+ end
73
+ end
74
+
75
+ def curr_json
76
+ @curr_json ||= []
77
+ end
78
+
79
+ def pending?
80
+ !input_json.empty?
81
+ end
82
+
83
+ def input_json
84
+ @json ||= JSON.load(File.open(input_file, 'r'))
85
+ end
86
+
87
+ # COUNTS
88
+
89
+ def next_count!
90
+ @curr_count = curr_count + 1
91
+ @total_count = total_count + 1
92
+ end
93
+
94
+ def total_count
95
+ @total_count ||= 0
96
+ end
97
+
98
+ def curr_count
99
+ @curr_count ||= 0
100
+ end
101
+
102
+ def new_count!
103
+ @curr_count = 0
104
+ end
105
+
106
+ # FILE GENERATION
107
+
108
+ def swap_file!
109
+ generate_file!
110
+ next_file!
111
+ end
112
+
113
+ def generate_file!
114
+ return unless @curr_file
115
+
116
+ if curr_json.empty?
117
+ log(:info) {
118
+ msg = "No pending elements to be transferred "
119
+ msg << "(skipping creation of file '#{curr_file}')"
120
+ msg
121
+ }
122
+ out_files -= [curr_file]
123
+ return
124
+ end
125
+
126
+ log(:info) {
127
+ msg = "Generating file at elem #{total_count} "
128
+ msg << "(file elements: #{curr_count})"
129
+ msg
130
+ }
131
+
132
+ save_json(exporting_json!, curr_file)
133
+ new_count!
134
+ end
135
+
136
+ def save_json(data, file)
137
+ File.open(file, 'w') do |fd|
138
+ first = true
139
+
140
+ fd << '['
141
+ data.each do |elem|
142
+ fd << "," unless first
143
+ first = false
144
+
145
+ fd << elem.to_json
146
+ end
147
+ fd << ']'
148
+ end.tap do
149
+ log(:info) {
150
+ "Generated file '#{file}'"
151
+ }
152
+ end
153
+ end
154
+
155
+ # OUTPUT FILES
156
+ attr_reader :curr_file
157
+
158
+ def file_count
159
+ @file_count ||= 0
160
+ end
161
+
162
+ def next_file!
163
+ @file_count = file_count + 1
164
+ @curr_file = generate_name(@file_count)
165
+ @curr_file.tap do
166
+ out_files << @curr_file
167
+ end
168
+ end
169
+
170
+ def out_files
171
+ @out_files ||= []
172
+ end
173
+
174
+ def generate_name(fidx)
175
+ File.join(input_dir, "#{input_name}_#{file_number(fidx)}#{input_ext}")
176
+ end
177
+
178
+ def file_number(num)
179
+ "#{zeroed}#{num}"[-5..]
180
+ end
181
+
182
+ def zeroed
183
+ "0" * 5
184
+ end
185
+
186
+ # INPUT FILE
187
+
188
+ def input_name
189
+ @input_name ||= File.basename(input_basename, input_ext)
190
+ end
191
+
192
+ def input_ext
193
+ @input_ext ||= input_basename.split('.')[1..].join('.').then do |name|
194
+ ".#{name}"
195
+ end
196
+ end
197
+
198
+ def input_basename
199
+ @input_basename ||= File.basename(input_full_filename)
200
+ end
201
+
202
+ def input_dir
203
+ @input_dir = File.dirname(input_full_filename)
204
+ end
205
+
206
+ def input_full_filename
207
+ @input_full_filename ||= File.expand_path(input_file)
208
+ end
209
+
210
+ def input_file
211
+ options.dig(:source, :file).tap do |file|
212
+ next if file && File.exist?(file)
213
+
214
+ unless file
215
+ log(:warn) { 'No input file provided' }
216
+ exit 1
217
+ end
218
+
219
+ log(:warn) {
220
+ "File '#{file}' doesn't exist"
221
+ }
222
+ end
223
+ end
224
+ end
@@ -10,3 +10,7 @@ module Eco
10
10
  end
11
11
 
12
12
  require_relative 'utils/split_csv_case'
13
+ require_relative 'utils/split_json_case'
14
+ require_relative 'utils/json_to_csv_case'
15
+ require_relative 'utils/sort_csv_case'
16
+ require_relative 'utils/group_csv_case'
@@ -7,7 +7,7 @@ class Eco::API::UseCases::DefaultCases::Samples::Sftp < Eco::API::Common::Loader
7
7
  name "sftp"
8
8
  type :other
9
9
 
10
- CONST_REFERRAL = /^(?:::)?(?:[A-Z][a-zA-Z0-9_]*(?:::[A-Z][a-zA-Z0-9_]*)*)$/.freeze
10
+ CONST_REFERRAL = /^(?:::)?(?:[A-Z][a-zA-Z0-9_]*(?:::[A-Z][a-zA-Z0-9_]*)*)$/
11
11
 
12
12
  def main(session, options, _usecase)
13
13
  options[:end_get] = false
@@ -31,7 +31,7 @@ class Eco::API::UseCases::DefaultCases::Samples::Sftp < Eco::API::Common::Loader
31
31
  def file_pattern(require: true)
32
32
  fpc = file_pattern_const
33
33
  return fpc if fpc
34
- return unless require
34
+ return unless require
35
35
 
36
36
  msg = "(#{self.class}) You should redefine the file_pattern function "
37
37
  msg << "as a RegEx expression that matches the target remote file"
@@ -41,6 +41,7 @@ class Eco::API::UseCases::DefaultCases::Samples::Sftp < Eco::API::Common::Loader
41
41
  def file_pattern_const
42
42
  if (fpc = options.dig(:sftp, :file_pattern_const))
43
43
  raise WrongConst, "(#{self.class}) Invalid file pattern const referral: #{fpc}" unless fpc.match(CONST_REFERRAL)
44
+
44
45
  begin
45
46
  self.eval(fpc)
46
47
  rescue NameError
@@ -54,6 +55,7 @@ class Eco::API::UseCases::DefaultCases::Samples::Sftp < Eco::API::Common::Loader
54
55
  # Ex: "/IN/Personnel"
55
56
  def remote_subfolder(require: true)
56
57
  rm_sf = options.dig(:sftp, :remote_subfolder)
58
+
57
59
  return rm_sf if rm_sf
58
60
  return unless require
59
61
 
@@ -78,7 +80,7 @@ class Eco::API::UseCases::DefaultCases::Samples::Sftp < Eco::API::Common::Loader
78
80
  options.dig(:sftp, :local_folder) || "."
79
81
  end
80
82
 
81
- def with_remote_files(folder: self.remote_folder, pattern: self.file_pattern)
83
+ def with_remote_files(folder: remote_folder, pattern: file_pattern)
82
84
  sftp.files(folder, pattern: pattern).each do |remote_file|
83
85
  yield(remote_file) if block_given?
84
86
  end
@@ -100,22 +102,25 @@ class Eco::API::UseCases::DefaultCases::Samples::Sftp < Eco::API::Common::Loader
100
102
 
101
103
  def get_files
102
104
  with_remote_files.tap do |files|
103
- unless files.empty?
104
- file_names = files.map {|file| to_remote_path(file.name)}
105
- puts "Getting the following files into the local folder '#{local_folder}':"
106
- puts file_names
107
- sftp.download(file_names, local_folder: local_folder)
108
- end
105
+ next if files.empty?
106
+
107
+ file_names = files.map {|file| to_remote_path(file.name)}
108
+
109
+ puts "Getting the following files into the local folder '#{local_folder}':"
110
+ puts file_names
111
+
112
+ sftp.download(file_names, local_folder: local_folder)
109
113
  end
110
114
  end
111
115
 
112
116
  def get_last
113
117
  with_remote_files.last.tap do |file|
114
- if file
115
- file_name = to_remote_path(file.name)
116
- puts "Getting the following file: #{file_name}"
117
- sftp.download(file_name, local_folder: local_folder)
118
- end
118
+ next unless file
119
+
120
+ file_name = to_remote_path(file.name)
121
+ puts "Getting the following file: #{file_name}"
122
+
123
+ sftp.download(file_name, local_folder: local_folder)
119
124
  end
120
125
  end
121
126
 
@@ -125,7 +130,9 @@ class Eco::API::UseCases::DefaultCases::Samples::Sftp < Eco::API::Common::Loader
125
130
  dest = to_remote_path("#{archive_subfolder}/#{file.name}")
126
131
  move_file(source, dest)
127
132
  end.tap do |files|
128
- puts "Moved the file(s) to the #{archive_subfolder} folder" unless files.empty?
133
+ next if files.empty?
134
+
135
+ puts "Moved the file(s) to the #{archive_subfolder} folder"
129
136
  end
130
137
  end
131
138
 
@@ -40,7 +40,7 @@ class Eco::API::UseCases::OozeCases::ExportRegisterCase < Eco::API::UseCases::Oo
40
40
 
41
41
  def build_tags_filter(mode = :any)
42
42
  tags = option_tags(mode)
43
- return nil if !tags || tags.empty?
43
+ return if !tags || tags.empty?
44
44
 
45
45
  tags_filter(tags, any: mode == :any)
46
46
  end
@@ -48,7 +48,7 @@ class Eco::API::UseCases::OozeCases::ExportRegisterCase < Eco::API::UseCases::Oo
48
48
  def build_range_filter(key = :update_at)
49
49
  from = from_date(key)
50
50
  to = to_date(key)
51
- return nil unless from || to
51
+ return unless from || to
52
52
 
53
53
  date_range_filter(from: from, to: to, key: key)
54
54
  end
@@ -92,10 +92,10 @@ class Eco::API::UseCases::OozeCases::ExportRegisterCase < Eco::API::UseCases::Oo
92
92
 
93
93
  def filename
94
94
  @filename ||= (options[:file] || options.dig(:export, :file, :name)).tap do |filename|
95
- unless filename
96
- log(:error) { "Destination file not specified" }
97
- return false
98
- end
95
+ next if filename
96
+
97
+ log(:error) { "Destination file not specified" }
98
+ return false
99
99
  end
100
100
  end
101
101
  end
@@ -48,6 +48,7 @@ module Eco
48
48
 
49
49
  def header(refresh: false)
50
50
  return @header if instance_variable_defined?(:@header) && !refresh
51
+
51
52
  @header = typed_header.map do |name|
52
53
  ExportableOoze.key_to_label(name)
53
54
  end
@@ -234,7 +234,7 @@ class Eco::API::UseCases::OozeSamples::OozeBaseCase < Eco::API::Common::Loaders:
234
234
 
235
235
  def dry_count
236
236
  @dry_count ||= 0
237
- @dry_count += 1
237
+ @dry_count += 1
238
238
  end
239
239
 
240
240
  def dry_run_feedback(entry = target)
@@ -3,17 +3,19 @@ class Eco::API::UseCases::OozeSamples::OozeRunBaseCase < Eco::API::UseCases::Ooz
3
3
  name "ooze-run-base"
4
4
  type :other
5
5
 
6
- SAVE_PATCH = "ooze_patch_update.json"
6
+ SAVE_PATCH = "ooze_patch_update.json".freeze
7
7
 
8
8
  def main(session, options, usecase)
9
9
  super(session, options, usecase) do
10
- if method(:process_ooze).parameters.count == 0
10
+ if method(:process_ooze).parameters.count.zero?
11
11
  ooze # retrieve ooze
12
12
  process_ooze
13
13
  else
14
14
  process_ooze(ooze)
15
15
  end
16
+
16
17
  yield(target) if block_given?
18
+
17
19
  exit_if_no_changes!
18
20
  update_ooze(target)
19
21
  end
@@ -30,7 +32,7 @@ class Eco::API::UseCases::OozeSamples::OozeRunBaseCase < Eco::API::UseCases::Ooz
30
32
  end
31
33
 
32
34
  def stage(stage_id_name = stage_id, ooze: target)
33
- super(stage_id_name, ooze: ooze)
35
+ super
34
36
  end
35
37
 
36
38
  def ooze_id
@@ -43,11 +45,12 @@ class Eco::API::UseCases::OozeSamples::OozeRunBaseCase < Eco::API::UseCases::Ooz
43
45
 
44
46
  def update_ooze(ooz = target)
45
47
  prompt_to_confirm!
46
- super(ooz)
48
+
49
+ super
47
50
  end
48
51
 
49
52
  def exit_if_no_changes!
50
- return if (changes = !!patch_doc["page"])
53
+ return if !!patch_doc["page"]
51
54
 
52
55
  log(:info) { "No Changes!!" }
53
56
  exit(0)
@@ -1,12 +1,14 @@
1
1
  ASSETS.cli do |cli| # rubocop:disable Metrics/BlockLength
2
2
  ASSETS.config.workflow do |wf| # rubocop:disable Metrics/BlockLength
3
3
  rescued = false
4
+
4
5
  # default rescue
5
6
  wf.rescue do |err, io|
6
7
  next io if rescued
7
8
 
8
9
  rescued = true
9
10
  log(:debug) { err.patch_full_message }
11
+
10
12
  wf.run(:close, io: io)
11
13
  rescue StandardError => e
12
14
  puts "Some problem in workflow.rescue: #{e}"
@@ -74,10 +76,10 @@ ASSETS.cli do |cli| # rubocop:disable Metrics/BlockLength
74
76
  end
75
77
 
76
78
  wf.on(:usecases) do |_wf_ca, io|
77
- unless cli.config.usecases.process(io: io)
78
- log(:info) { "No update operation specified... quitting" }
79
- exit 0
80
- end
79
+ next if cli.config.usecases.process(io: io)
80
+
81
+ log(:info) { "No update operation specified... quitting" }
82
+ exit 0
81
83
  end
82
84
 
83
85
  wf.before(:launch_jobs) do |_wf_jobs, _io|
@@ -95,11 +97,13 @@ ASSETS.cli do |cli| # rubocop:disable Metrics/BlockLength
95
97
  run_it = !options[:dry_run] || options.dig(:post_launch, :run)
96
98
  unless run_it
97
99
  wf_post.skip!
100
+
98
101
  log(:info) {
99
102
  msg = "Although there are post_launch cases, they will NOT be RUN"
100
103
  msg << ", because we are in dry-run (simulate)." if options[:dry_run]
101
104
  msg
102
105
  }
106
+
103
107
  next
104
108
  end
105
109
 
@@ -117,6 +121,7 @@ ASSETS.cli do |cli| # rubocop:disable Metrics/BlockLength
117
121
  end
118
122
  msg
119
123
  }
124
+
120
125
  next
121
126
  end
122
127
 
@@ -131,6 +136,7 @@ ASSETS.cli do |cli| # rubocop:disable Metrics/BlockLength
131
136
  use.launch(io: io).base
132
137
  rescue Eco::API::UseCases::BaseIO::MissingParameter => e
133
138
  raise unless e.required == :people
139
+
134
140
  log(:debug) {
135
141
  "Skipping use case '#{use.name}' -- no base people detected for the current run"
136
142
  }
@@ -7,6 +7,7 @@ module Eco
7
7
 
8
8
  def initialize(filename, **kargs)
9
9
  raise ArgumentError, "File '#{filename}' does not exist" unless ::File.exist?(filename)
10
+
10
11
  @filename = filename
11
12
  @params = {
12
13
  headers: true,
@@ -55,6 +56,7 @@ module Eco
55
56
  # see https://dalibornasevic.com/posts/68-processing-large-csv-files-with-ruby
56
57
  def csv
57
58
  return @csv if instance_variable_defined?(:@csv)
59
+
58
60
  @fd = ::File.open(filename, 'r')
59
61
  @csv = Eco::CSV.new(fd, **params)
60
62
  end
data/lib/eco/csv.rb CHANGED
@@ -5,9 +5,9 @@ module Eco
5
5
  include Eco::Data::Files
6
6
 
7
7
  # @return [Eco::CSV::Table]
8
- def parse(data, **kargs, &block)
8
+ def parse(data, **kargs)
9
9
  kargs = {headers: true, skip_blanks: true}.merge(kargs)
10
- Eco::CSV::Table.new(super(data, **kargs, &block))
10
+ Eco::CSV::Table.new(super)
11
11
  end
12
12
 
13
13
  # @return [Eco::CSV::Table]
@@ -51,6 +51,7 @@ module Eco
51
51
  included = yield(row) if block_given?
52
52
  count += 1 if included
53
53
  end
54
+
54
55
  count
55
56
  end
56
57
  end
@@ -7,7 +7,7 @@ module Eco
7
7
  end
8
8
 
9
9
  def method_missing(method_name, *args, **kargs, &block)
10
- super unless receiver = object_missing_delegated_to
10
+ super unless (receiver = object_missing_delegated_to)
11
11
  receiver.send(method_name, *args, **kargs, &block)
12
12
  end
13
13
 
@@ -19,8 +19,9 @@ module Eco
19
19
 
20
20
  # retrieve the delegate_missing_to object
21
21
  def object_missing_delegated_to
22
- return nil unless @delegate_missing_to
23
- self.method(@delegate_missing_to).call
22
+ return unless @delegate_missing_to
23
+
24
+ method(@delegate_missing_to).call
24
25
  end
25
26
  end
26
27
  end
data/lib/eco/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eco
2
- VERSION = '3.0.18'.freeze
2
+ VERSION = '3.0.20'.freeze
3
3
  end