csv_decision 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -1
  3. data/README.md +11 -8
  4. data/benchmarks/rufus_decision.rb +9 -1
  5. data/csv_decision.gemspec +1 -1
  6. data/doc/CSVDecision/CellValidationError.html +1 -1
  7. data/doc/CSVDecision/Columns/Dictionary.html +29 -29
  8. data/doc/CSVDecision/Columns.html +394 -47
  9. data/doc/CSVDecision/Data.html +2 -2
  10. data/doc/CSVDecision/Decide.html +23 -159
  11. data/doc/CSVDecision/Decision.html +370 -32
  12. data/doc/CSVDecision/Defaults.html +1 -1
  13. data/doc/CSVDecision/Dictionary/Entry.html +157 -55
  14. data/doc/CSVDecision/Dictionary.html +37 -21
  15. data/doc/CSVDecision/Error.html +1 -1
  16. data/doc/CSVDecision/FileError.html +1 -1
  17. data/doc/CSVDecision/Header.html +142 -1
  18. data/doc/CSVDecision/Index.html +741 -0
  19. data/doc/CSVDecision/Input.html +14 -61
  20. data/doc/CSVDecision/Load.html +1 -1
  21. data/doc/CSVDecision/Matchers/Constant.html +1 -1
  22. data/doc/CSVDecision/Matchers/Function.html +1 -1
  23. data/doc/CSVDecision/Matchers/Guard.html +13 -147
  24. data/doc/CSVDecision/Matchers/Matcher.html +13 -13
  25. data/doc/CSVDecision/Matchers/Numeric.html +1 -1
  26. data/doc/CSVDecision/Matchers/Pattern.html +1 -1
  27. data/doc/CSVDecision/Matchers/Proc.html +147 -14
  28. data/doc/CSVDecision/Matchers/Range.html +1 -1
  29. data/doc/CSVDecision/Matchers/Symbol.html +1 -1
  30. data/doc/CSVDecision/Matchers.html +55 -162
  31. data/doc/CSVDecision/Options.html +21 -21
  32. data/doc/CSVDecision/Parse.html +2 -180
  33. data/doc/CSVDecision/Result.html +220 -38
  34. data/doc/CSVDecision/ScanRow.html +69 -325
  35. data/doc/CSVDecision/Table.html +128 -40
  36. data/doc/CSVDecision/TableValidationError.html +1 -1
  37. data/doc/CSVDecision/Validate.html +1 -1
  38. data/doc/CSVDecision.html +4 -4
  39. data/doc/_index.html +8 -8
  40. data/doc/class_list.html +1 -1
  41. data/doc/file.README.html +13 -11
  42. data/doc/index.html +13 -11
  43. data/doc/method_list.html +206 -150
  44. data/doc/top-level-namespace.html +1 -1
  45. data/lib/csv_decision/columns.rb +87 -1
  46. data/lib/csv_decision/decision.rb +54 -29
  47. data/lib/csv_decision/defaults.rb +1 -1
  48. data/lib/csv_decision/dictionary.rb +32 -22
  49. data/lib/csv_decision/header.rb +17 -0
  50. data/lib/csv_decision/index.rb +107 -0
  51. data/lib/csv_decision/input.rb +45 -13
  52. data/lib/csv_decision/matchers/guard.rb +2 -0
  53. data/lib/csv_decision/matchers.rb +14 -8
  54. data/lib/csv_decision/options.rb +7 -19
  55. data/lib/csv_decision/parse.rb +12 -96
  56. data/lib/csv_decision/result.rb +10 -9
  57. data/lib/csv_decision/scan_row.rb +20 -44
  58. data/lib/csv_decision/table.rb +7 -4
  59. data/lib/csv_decision.rb +1 -1
  60. data/spec/csv_decision/columns_spec.rb +6 -6
  61. data/spec/csv_decision/data_spec.rb +0 -5
  62. data/spec/csv_decision/index_spec.rb +58 -0
  63. data/spec/csv_decision/input_spec.rb +7 -2
  64. data/spec/csv_decision/options_spec.rb +16 -1
  65. data/spec/csv_decision/parse_spec.rb +4 -5
  66. data/spec/csv_decision/table_spec.rb +70 -0
  67. data/spec/data/{valid → invalid}/empty.csv +0 -0
  68. data/spec/data/valid/index_example.csv +12 -0
  69. data/spec/data/valid/multi_column_index.csv +10 -0
  70. data/spec/data/valid/multi_column_index2.csv +12 -0
  71. data/spec/data/valid/options_in_file3.csv +13 -0
  72. metadata +16 -5
  73. data/lib/csv_decision/decide.rb +0 -45
@@ -490,5 +490,75 @@ describe CSVDecision::Table do
490
490
  end
491
491
  end
492
492
  end
493
+
494
+ context 'uses single column index to make correct decisions' do
495
+ examples = [
496
+ { example: 'evaluates single-column index CSV string',
497
+ options: { first_match: false },
498
+ data: <<~DATA
499
+ in:topic, in:region, out:team_member
500
+ sports, Europe, Alice
501
+ sports, , Bob
502
+ finance, America, Charlie
503
+ finance, Europe, Donald
504
+ finance, , Ernest
505
+ politics, Asia, Fujio
506
+ politics, America, Gilbert
507
+ politics, , Henry
508
+ sports, , Zach
509
+ finance, , Zach
510
+ politics, , Zach
511
+ DATA
512
+ },
513
+ { example: 'evaluates single-column index CSV file',
514
+ options: { first_match: false },
515
+ data: Pathname(File.join(SPEC_DATA_VALID, 'index_example.csv'))
516
+ }
517
+ ]
518
+ examples.each do |test|
519
+ %i[decide decide!].each do |method|
520
+ it "#{method} correctly #{test[:example]}" do
521
+ table = CSVDecision.parse(test[:data], test[:options])
522
+
523
+ expect(table.send(method, topic: 'politics', region: 'Arctic'))
524
+ .to eq(team_member: %w[Henry Zach])
525
+ end
526
+ end
527
+ end
528
+ end
529
+
530
+ context 'uses multi-column index to make correct decisions' do
531
+ examples = [
532
+ { example: 'evaluates multi-column index CSV string',
533
+ options: { first_match: true },
534
+ data: <<~DATA
535
+ guard:, in :type, IN :input, OUT :output
536
+ :number.present?, integer, none, :=0
537
+ :number.blank?, integer, none, :=nil
538
+ :number.present?, integer, one, :=1
539
+ :number.blank?, integer, one, :=nil
540
+ :string.present?, string, none, 0
541
+ :number.blank?, string, none, :=nil
542
+ :string.present?, string, one, 1
543
+ :number.blank?, string, one, :=nil
544
+ DATA
545
+ },
546
+ { example: 'evaluates multi-column index CSV file',
547
+ options: { first_match: true },
548
+ data: Pathname(File.join(SPEC_DATA_VALID, 'multi_column_index.csv'))
549
+ }
550
+ ]
551
+ examples.each do |test|
552
+ %i[decide decide!].each do |method|
553
+ it "#{method} correctly #{test[:example]}" do
554
+ table = CSVDecision.parse(test[:data], test[:options])
555
+
556
+ expect(table.send(method, number: 1, type: 'integer', input: 'none')).to eq(output: 0)
557
+ expect(table.send(method, number: nil, type: 'string', input: 'one')).to eq(output: nil)
558
+ expect(table.send(method, string: '1', type: 'string', input: 'one')).to eq(output: '1')
559
+ end
560
+ end
561
+ end
562
+ end
493
563
  end
494
564
  end
File without changes
@@ -0,0 +1,12 @@
1
+ in:topic,in:region,out:team_member
2
+ sports,Europe,Alice
3
+ sports,,Bob
4
+ finance,America,Charlie
5
+ finance,Europe,Donald
6
+ finance,,Ernest
7
+ politics,Asia,Fujio
8
+ politics,America,Gilbert
9
+ politics,,Henry
10
+ sports,,Zach
11
+ finance,,Zach
12
+ politics,,Zach
@@ -0,0 +1,10 @@
1
+ #comment,
2
+ guard:,in :type, IN :input,OUT :output
3
+ :number.present?,integer,none,:=0
4
+ :number.blank?,integer,none,:=nil
5
+ :number.present?,integer,one,:=1
6
+ :number.blank?,integer,one,:=nil
7
+ :string.present?,string,none,0
8
+ :number.blank?,string,none,:=nil
9
+ :string.present?,string,one,1
10
+ :number.blank?,string,one,:=nil
@@ -0,0 +1,12 @@
1
+ #comment,
2
+ index : 2
3
+ guard:,in :type, IN :input,OUT :output
4
+ :number.present?,integer,none,:=0
5
+ :string.blank?,string,none,:=nil
6
+ :string.present?,string,none,0
7
+ :string.blank?,string,one,:=nil
8
+ :number.present?,integer,one,:=1
9
+ :number.blank?,integer,one,:=nil
10
+ :string.present?,string,one,1
11
+ :string.blank?,string,one,:=nil
12
+ :number.blank?,integer,none,:=nil
@@ -0,0 +1,13 @@
1
+ #comment,
2
+ accumulate, index : 1
3
+ regexp_implicit
4
+ IN :input,OUT :output
5
+ none,:=0
6
+ one,:=1
7
+ two,:=2
8
+ three,:=3
9
+ :=nil,none
10
+ :=0,none
11
+ :=1,one
12
+ :=2,two
13
+ :=3,three
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: csv_decision
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Vickers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-13 00:00:00.000000000 Z
11
+ date: 2018-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -187,6 +187,7 @@ files:
187
187
  - doc/CSVDecision/Function.html
188
188
  - doc/CSVDecision/Guard.html
189
189
  - doc/CSVDecision/Header.html
190
+ - doc/CSVDecision/Index.html
190
191
  - doc/CSVDecision/Input.html
191
192
  - doc/CSVDecision/Load.html
192
193
  - doc/CSVDecision/Matchers.html
@@ -225,11 +226,11 @@ files:
225
226
  - lib/csv_decision.rb
226
227
  - lib/csv_decision/columns.rb
227
228
  - lib/csv_decision/data.rb
228
- - lib/csv_decision/decide.rb
229
229
  - lib/csv_decision/decision.rb
230
230
  - lib/csv_decision/defaults.rb
231
231
  - lib/csv_decision/dictionary.rb
232
232
  - lib/csv_decision/header.rb
233
+ - lib/csv_decision/index.rb
233
234
  - lib/csv_decision/input.rb
234
235
  - lib/csv_decision/load.rb
235
236
  - lib/csv_decision/matchers.rb
@@ -251,6 +252,7 @@ files:
251
252
  - spec/csv_decision/data_spec.rb
252
253
  - spec/csv_decision/decision_spec.rb
253
254
  - spec/csv_decision/examples_spec.rb
255
+ - spec/csv_decision/index_spec.rb
254
256
  - spec/csv_decision/input_spec.rb
255
257
  - spec/csv_decision/load_spec.rb
256
258
  - spec/csv_decision/matchers/function_spec.rb
@@ -263,14 +265,18 @@ files:
263
265
  - spec/csv_decision/parse_spec.rb
264
266
  - spec/csv_decision/table_spec.rb
265
267
  - spec/csv_decision_spec.rb
268
+ - spec/data/invalid/empty.csv
266
269
  - spec/data/invalid/invalid_header1.csv
267
270
  - spec/data/invalid/invalid_header2.csv
268
271
  - spec/data/invalid/invalid_header3.csv
269
272
  - spec/data/invalid/invalid_header4.csv
270
273
  - spec/data/valid/benchmark_regexp.csv
271
- - spec/data/valid/empty.csv
274
+ - spec/data/valid/index_example.csv
275
+ - spec/data/valid/multi_column_index.csv
276
+ - spec/data/valid/multi_column_index2.csv
272
277
  - spec/data/valid/options_in_file1.csv
273
278
  - spec/data/valid/options_in_file2.csv
279
+ - spec/data/valid/options_in_file3.csv
274
280
  - spec/data/valid/regular_expressions.csv
275
281
  - spec/data/valid/simple_constants.csv
276
282
  - spec/data/valid/simple_example.csv
@@ -308,6 +314,7 @@ test_files:
308
314
  - spec/csv_decision/data_spec.rb
309
315
  - spec/csv_decision/decision_spec.rb
310
316
  - spec/csv_decision/examples_spec.rb
317
+ - spec/csv_decision/index_spec.rb
311
318
  - spec/csv_decision/input_spec.rb
312
319
  - spec/csv_decision/load_spec.rb
313
320
  - spec/csv_decision/matchers/function_spec.rb
@@ -320,14 +327,18 @@ test_files:
320
327
  - spec/csv_decision/parse_spec.rb
321
328
  - spec/csv_decision/table_spec.rb
322
329
  - spec/csv_decision_spec.rb
330
+ - spec/data/invalid/empty.csv
323
331
  - spec/data/invalid/invalid_header1.csv
324
332
  - spec/data/invalid/invalid_header2.csv
325
333
  - spec/data/invalid/invalid_header3.csv
326
334
  - spec/data/invalid/invalid_header4.csv
327
335
  - spec/data/valid/benchmark_regexp.csv
328
- - spec/data/valid/empty.csv
336
+ - spec/data/valid/index_example.csv
337
+ - spec/data/valid/multi_column_index.csv
338
+ - spec/data/valid/multi_column_index2.csv
329
339
  - spec/data/valid/options_in_file1.csv
330
340
  - spec/data/valid/options_in_file2.csv
341
+ - spec/data/valid/options_in_file3.csv
331
342
  - spec/data/valid/regular_expressions.csv
332
343
  - spec/data/valid/simple_constants.csv
333
344
  - spec/data/valid/simple_example.csv
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # CSV Decision: CSV based Ruby decision tables.
4
- # Created December 2017.
5
- # @author Brett Vickers <brett@phillips-vickers.com>
6
- # See LICENSE and README.md for details.
7
- module CSVDecision
8
- # Main module for searching the decision table looking for one or more matches
9
- # @api private
10
- module Decide
11
- # Match the table row against the input hash.
12
- #
13
- # @param row [Array] Table row.
14
- # @param input [Hash{Symbol=>Object}] Input hash data structure.
15
- # @param scan_row [ScanRow]
16
- # @return [Boolean] Returns true if a match, false otherwise.
17
- def self.matches?(row:, input:, scan_row:)
18
- match = scan_row.match_constants?(row: row, scan_cols: input[:scan_cols])
19
- return false unless match
20
-
21
- return true if scan_row.procs.empty?
22
-
23
- scan_row.match_procs?(row: row, input: input)
24
- end
25
-
26
- # Main method for making decisions.
27
- #
28
- # @param table [CSVDecision::Table] Decision table.
29
- # @param input [Hash] Input hash (keys may or may not be symbolized)
30
- # @param symbolize_keys [true, false] Set to false if keys are symbolized and it's
31
- # OK to mutate the input hash. Otherwise a copy of the input hash is symbolized.
32
- # @return [Hash] Decision result.
33
- def self.decide(table:, input:, symbolize_keys:)
34
- # Parse and transform the hash supplied as input
35
- parsed_input = Input.parse(table: table, input: input, symbolize_keys: symbolize_keys)
36
-
37
- # The decision object collects the results of the search and
38
- # calculates the final result
39
- decision = Decision.new(table: table, input: parsed_input)
40
-
41
- # table_scan(table: table, input: parsed_input, decision: decision)
42
- decision.scan(table: table, input: parsed_input)
43
- end
44
- end
45
- end