csv_decision2 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/README.md +16 -16
- data/benchmarks/rufus_decision.rb +5 -7
- data/csv_decision2.gemspec +2 -2
- data/doc/CSVDecision/CellValidationError.html +117 -110
- data/doc/CSVDecision/Columns/Default.html +537 -508
- data/doc/CSVDecision/Columns/Dictionary.html +729 -686
- data/doc/CSVDecision/Columns/Entry.html +457 -433
- data/doc/CSVDecision/Columns.html +1134 -1051
- data/doc/CSVDecision/Constant.html +205 -191
- data/doc/CSVDecision/Data.html +423 -398
- data/doc/CSVDecision/Decide.html +236 -225
- data/doc/CSVDecision/Decision.html +872 -825
- data/doc/CSVDecision/Defaults.html +243 -230
- data/doc/CSVDecision/Dictionary/Entry.html +1026 -964
- data/doc/CSVDecision/Dictionary.html +377 -355
- data/doc/CSVDecision/Error.html +116 -105
- data/doc/CSVDecision/FileError.html +117 -110
- data/doc/CSVDecision/Function.html +181 -168
- data/doc/CSVDecision/Guard.html +200 -185
- data/doc/CSVDecision/Header.html +557 -523
- data/doc/CSVDecision/Index.html +652 -617
- data/doc/CSVDecision/Input.html +329 -312
- data/doc/CSVDecision/Load.html +232 -220
- data/doc/CSVDecision/Matchers/Constant.html +432 -399
- data/doc/CSVDecision/Matchers/Function.html +451 -415
- data/doc/CSVDecision/Matchers/Guard.html +459 -424
- data/doc/CSVDecision/Matchers/Matcher.html +470 -426
- data/doc/CSVDecision/Matchers/Numeric.html +375 -346
- data/doc/CSVDecision/Matchers/Pattern.html +429 -396
- data/doc/CSVDecision/Matchers/Proc.html +617 -575
- data/doc/CSVDecision/Matchers/Range.html +331 -302
- data/doc/CSVDecision/Matchers/Symbol.html +386 -353
- data/doc/CSVDecision/Matchers.html +1509 -1393
- data/doc/CSVDecision/Numeric.html +201 -188
- data/doc/CSVDecision/Options.html +376 -357
- data/doc/CSVDecision/Parse.html +217 -204
- data/doc/CSVDecision/Paths.html +664 -629
- data/doc/CSVDecision/Result.html +1076 -1005
- data/doc/CSVDecision/Scan/InputHashes.html +305 -288
- data/doc/CSVDecision/Scan.html +262 -249
- data/doc/CSVDecision/ScanRow.html +749 -705
- data/doc/CSVDecision/Symbol.html +204 -191
- data/doc/CSVDecision/Table.html +1391 -1305
- data/doc/CSVDecision/TableValidationError.html +117 -110
- data/doc/CSVDecision/Validate.html +353 -337
- data/doc/CSVDecision.html +623 -552
- data/doc/_index.html +488 -448
- data/doc/class_list.html +250 -45
- data/doc/file.README.html +304 -278
- data/doc/index.html +304 -278
- data/doc/method_list.html +1159 -1017
- data/doc/top-level-namespace.html +79 -75
- data/lib/{csv_decision → csv_decision2}/columns.rb +7 -7
- data/lib/{csv_decision → csv_decision2}/data.rb +1 -1
- data/lib/{csv_decision → csv_decision2}/decision.rb +5 -5
- data/lib/{csv_decision → csv_decision2}/defaults.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/dictionary.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/header.rb +5 -5
- data/lib/{csv_decision → csv_decision2}/index.rb +5 -5
- data/lib/{csv_decision → csv_decision2}/input.rb +3 -3
- data/lib/{csv_decision → csv_decision2}/load.rb +6 -6
- data/lib/{csv_decision → csv_decision2}/matchers/constant.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/matchers/function.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/matchers/guard.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/matchers/numeric.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/matchers/pattern.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/matchers/range.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/matchers/symbol.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/matchers.rb +5 -5
- data/lib/{csv_decision → csv_decision2}/options.rb +3 -3
- data/lib/{csv_decision → csv_decision2}/parse.rb +14 -14
- data/lib/{csv_decision → csv_decision2}/paths.rb +5 -5
- data/lib/{csv_decision → csv_decision2}/result.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/scan.rb +3 -3
- data/lib/{csv_decision → csv_decision2}/scan_row.rb +2 -2
- data/lib/{csv_decision → csv_decision2}/table.rb +8 -8
- data/lib/{csv_decision → csv_decision2}/validate.rb +2 -2
- data/lib/csv_decision2.rb +45 -0
- data/spec/{csv_decision → csv_decision2}/columns_spec.rb +44 -44
- data/spec/{csv_decision → csv_decision2}/constant_spec.rb +4 -4
- data/spec/{csv_decision → csv_decision2}/data_spec.rb +11 -11
- data/spec/{csv_decision → csv_decision2}/decision_spec.rb +6 -6
- data/spec/{csv_decision → csv_decision2}/examples_spec.rb +14 -14
- data/spec/{csv_decision → csv_decision2}/index_spec.rb +8 -8
- data/spec/{csv_decision → csv_decision2}/input_spec.rb +9 -9
- data/spec/{csv_decision → csv_decision2}/load_spec.rb +8 -8
- data/spec/{csv_decision → csv_decision2}/matchers/function_spec.rb +7 -7
- data/spec/{csv_decision → csv_decision2}/matchers/guard_spec.rb +14 -14
- data/spec/{csv_decision → csv_decision2}/matchers/numeric_spec.rb +5 -5
- data/spec/{csv_decision → csv_decision2}/matchers/pattern_spec.rb +6 -6
- data/spec/{csv_decision → csv_decision2}/matchers/range_spec.rb +5 -5
- data/spec/{csv_decision → csv_decision2}/matchers/symbol_spec.rb +6 -6
- data/spec/{csv_decision → csv_decision2}/options_spec.rb +18 -18
- data/spec/csv_decision2/parse_spec.rb +44 -0
- data/spec/{csv_decision → csv_decision2}/table_spec.rb +17 -17
- data/spec/csv_decision2_spec.rb +7 -0
- metadata +64 -64
- data/lib/csv_decision.rb +0 -45
- data/spec/csv_decision/parse_spec.rb +0 -44
- data/spec/csv_decision_spec.rb +0 -7
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../lib/
|
3
|
+
require_relative '../../lib/csv_decision2'
|
4
4
|
|
5
5
|
context 'simple examples' do
|
6
6
|
context 'simple example - strings-only' do
|
@@ -18,7 +18,7 @@ context 'simple examples' do
|
|
18
18
|
DATA
|
19
19
|
|
20
20
|
it 'makes correct decisions for CSV string' do
|
21
|
-
table =
|
21
|
+
table = CSVDecision2.parse(data)
|
22
22
|
|
23
23
|
result = table.decide(topic: 'finance', region: 'Europe')
|
24
24
|
expect(result).to eq(team_member: 'Donald')
|
@@ -31,7 +31,7 @@ context 'simple examples' do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'makes correct decisions for CSV file' do
|
34
|
-
table =
|
34
|
+
table = CSVDecision2.parse(Pathname('spec/data/valid/simple_example.csv'))
|
35
35
|
|
36
36
|
result = table.decide(topic: 'finance', region: 'Europe')
|
37
37
|
expect(result).to eq(team_member: 'Donald')
|
@@ -55,7 +55,7 @@ context 'simple examples' do
|
|
55
55
|
DATA
|
56
56
|
|
57
57
|
it 'makes correct decisions for CSV string' do
|
58
|
-
table =
|
58
|
+
table = CSVDecision2.parse(data)
|
59
59
|
|
60
60
|
result = table.decide(constant: nil)
|
61
61
|
expect(result).to eq(value: nil)
|
@@ -82,7 +82,7 @@ context 'simple examples' do
|
|
82
82
|
DATA
|
83
83
|
|
84
84
|
it 'makes correct decisions' do
|
85
|
-
table =
|
85
|
+
table = CSVDecision2.parse(data)
|
86
86
|
|
87
87
|
result = table.decide(node: 0, parent: 0)
|
88
88
|
expect(result).to eq(top?: 'yes')
|
@@ -103,7 +103,7 @@ context 'simple examples' do
|
|
103
103
|
DATA
|
104
104
|
|
105
105
|
it 'makes correct decisions' do
|
106
|
-
table =
|
106
|
+
table = CSVDecision2.parse(data)
|
107
107
|
|
108
108
|
result = table.decide(node: 0, parent: 0)
|
109
109
|
expect(result).to eq(top?: 'yes')
|
@@ -124,7 +124,7 @@ context 'simple examples' do
|
|
124
124
|
, <:traded, invalid trade
|
125
125
|
, , invalid data
|
126
126
|
DATA
|
127
|
-
table =
|
127
|
+
table = CSVDecision2.parse(data)
|
128
128
|
|
129
129
|
expect(table.columns.input_keys).to eq %i[traded settled]
|
130
130
|
|
@@ -136,7 +136,7 @@ context 'simple examples' do
|
|
136
136
|
expect(table.decide(traded: 20171228, settled: 20171227 )).to eq(status: 'invalid trade')
|
137
137
|
expect(table.decide(traded: '20171227', settled: 20171228 )).to eq(status: 'invalid data')
|
138
138
|
end
|
139
|
-
|
139
|
+
|
140
140
|
it 'makes a correct decision using a guard column' do
|
141
141
|
data = <<~DATA
|
142
142
|
in :country, guard:, out :ID, out :ID_type, out :len
|
@@ -148,7 +148,7 @@ context 'simple examples' do
|
|
148
148
|
, , := nil, := nil, := nil
|
149
149
|
DATA
|
150
150
|
|
151
|
-
table =
|
151
|
+
table = CSVDecision2.parse(data)
|
152
152
|
|
153
153
|
expect(table.decide(country: 'US', CUSIP: '123456789'))
|
154
154
|
.to eq(ID: '123456789', ID_type: 'CUSIP', len: 9)
|
@@ -167,7 +167,7 @@ context 'simple examples' do
|
|
167
167
|
, :CUSIP.present?, :CUSIP, DUMMY, :ID.length,
|
168
168
|
DATA
|
169
169
|
|
170
|
-
table =
|
170
|
+
table = CSVDecision2.parse(data)
|
171
171
|
|
172
172
|
expect(table.decide(country: 'US', CUSIP: '12345678'))
|
173
173
|
.to eq(ID: '12345678', ID_type: 'CUSIP8', len: 8)
|
@@ -191,7 +191,7 @@ context 'simple examples' do
|
|
191
191
|
!=US, :ISIN.present?, PRIVATE, :ISIN, :PAID.length,
|
192
192
|
DATA
|
193
193
|
|
194
|
-
table =
|
194
|
+
table = CSVDecision2.parse(data)
|
195
195
|
expect(table.decide(CUSIP: '1234567890', class: 'Private')).to eq(PAID: '1234567890', len: 10)
|
196
196
|
expect(table.decide(CUSIP: '123456789', class: 'Public')).to eq(PAID: '123456789', len: 9)
|
197
197
|
expect(table.decide(ISIN: '123456789', country: 'GB', class: 'public')).to eq({})
|
@@ -208,7 +208,7 @@ context 'simple examples' do
|
|
208
208
|
!=US, , !.blank?, PRIVATE, :ISIN, :PAID.length,
|
209
209
|
DATA
|
210
210
|
|
211
|
-
table =
|
211
|
+
table = CSVDecision2.parse(data)
|
212
212
|
expect(table.decide(CUSIP: '1234567890', class: 'Private')).to eq(PAID: '1234567890', len: 10)
|
213
213
|
expect(table.decide(CUSIP: '123456789', class: 'Public')).to eq(PAID: '123456789', len: 9)
|
214
214
|
expect(table.decide(ISIN: '123456789', country: 'GB', class: 'public')).to eq({})
|
@@ -223,7 +223,7 @@ context 'simple examples' do
|
|
223
223
|
payload, , :amount
|
224
224
|
payload, ref_data, :account_id
|
225
225
|
DATA
|
226
|
-
table =
|
226
|
+
table = CSVDecision2.parse(data, first_match: false)
|
227
227
|
|
228
228
|
input = {
|
229
229
|
header: {
|
@@ -239,4 +239,4 @@ context 'simple examples' do
|
|
239
239
|
expect(table.decide(input)).to eq(value: %w[Client Trading 100.00 5010])
|
240
240
|
expect(table.decide!(input)).to eq(value: %w[Client Trading 100.00 5010])
|
241
241
|
end
|
242
|
-
end
|
242
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../lib/
|
3
|
+
require_relative '../../lib/csv_decision2'
|
4
4
|
|
5
|
-
SPEC_DATA_VALID ||= File.join(
|
6
|
-
SPEC_DATA_INVALID ||= File.join(
|
5
|
+
SPEC_DATA_VALID ||= File.join(CSVDecision2.root, 'spec', 'data', 'valid')
|
6
|
+
SPEC_DATA_INVALID ||= File.join(CSVDecision2.root, 'spec', 'data', 'invalid')
|
7
7
|
|
8
|
-
describe
|
8
|
+
describe CSVDecision2::Index do
|
9
9
|
it 'indexes a single column CSV' do
|
10
10
|
file = Pathname(File.join(SPEC_DATA_VALID, 'options_in_file3.csv'))
|
11
|
-
result =
|
11
|
+
result = CSVDecision2.parse(file)
|
12
12
|
|
13
13
|
expected = {
|
14
14
|
'none' => 0,
|
@@ -28,7 +28,7 @@ describe CSVDecision::Index do
|
|
28
28
|
|
29
29
|
it 'indexes two columns with contiguous values' do
|
30
30
|
file = Pathname(File.join(SPEC_DATA_VALID, 'multi_column_index.csv'))
|
31
|
-
result =
|
31
|
+
result = CSVDecision2.parse(file)
|
32
32
|
|
33
33
|
expected = {
|
34
34
|
%w[integer none] => [[0, 1]],
|
@@ -43,7 +43,7 @@ describe CSVDecision::Index do
|
|
43
43
|
|
44
44
|
it 'indexes two columns with non-contiguous values' do
|
45
45
|
file = Pathname(File.join(SPEC_DATA_VALID, 'multi_column_index2.csv'))
|
46
|
-
result =
|
46
|
+
result = CSVDecision2.parse(file)
|
47
47
|
|
48
48
|
expected = {
|
49
49
|
%w[integer none] => [0, 8],
|
@@ -55,4 +55,4 @@ describe CSVDecision::Index do
|
|
55
55
|
expect(result.index.columns).to eq [1, 2]
|
56
56
|
expect(result.index.hash).to eql expected
|
57
57
|
end
|
58
|
-
end
|
58
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../lib/
|
3
|
+
require_relative '../../lib/csv_decision2'
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe CSVDecision2::Input do
|
6
6
|
it 'rejects a non-hash or empty hash value' do
|
7
|
-
expect {
|
7
|
+
expect { CSVDecision2::Input.parse(table: nil, input: [], symbolize_keys: true ) }
|
8
8
|
.to raise_error(ArgumentError, 'input must be a non-empty hash')
|
9
|
-
expect {
|
9
|
+
expect { CSVDecision2::Input.parse(table: nil, input: {}, symbolize_keys: true ) }
|
10
10
|
.to raise_error(ArgumentError, 'input must be a non-empty hash')
|
11
11
|
end
|
12
12
|
|
@@ -17,7 +17,7 @@ describe CSVDecision::Input do
|
|
17
17
|
input0, output1,
|
18
18
|
DATA
|
19
19
|
|
20
|
-
table =
|
20
|
+
table = CSVDecision2.parse(data)
|
21
21
|
|
22
22
|
input = { 'input' => 'input0', input1: 'input1' }
|
23
23
|
expected = {
|
@@ -26,7 +26,7 @@ describe CSVDecision::Input do
|
|
26
26
|
key: 'input0'
|
27
27
|
}
|
28
28
|
|
29
|
-
result =
|
29
|
+
result = CSVDecision2::Input.parse(table: table, input: input, symbolize_keys: true)
|
30
30
|
|
31
31
|
expect(result).to eql expected
|
32
32
|
expect(result[:hash]).not_to equal expected[:hash]
|
@@ -39,7 +39,7 @@ describe CSVDecision::Input do
|
|
39
39
|
input0, output1,
|
40
40
|
DATA
|
41
41
|
|
42
|
-
table =
|
42
|
+
table = CSVDecision2.parse(data)
|
43
43
|
input = { input: 'input0', input1: 'input1' }
|
44
44
|
expected = {
|
45
45
|
hash: input,
|
@@ -47,9 +47,9 @@ describe CSVDecision::Input do
|
|
47
47
|
key: 'input0'
|
48
48
|
}
|
49
49
|
|
50
|
-
result =
|
50
|
+
result = CSVDecision2::Input.parse(table: table, input: input, symbolize_keys: false)
|
51
51
|
|
52
52
|
expect(result).to eql expected
|
53
53
|
expect(result[:hash]).to equal expected[:hash]
|
54
54
|
end
|
55
|
-
end
|
55
|
+
end
|
@@ -1,28 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../lib/
|
3
|
+
require_relative '../../lib/csv_decision2'
|
4
4
|
|
5
|
-
describe
|
6
|
-
path = Pathname(File.join(
|
5
|
+
describe CSVDecision2::Load do
|
6
|
+
path = Pathname(File.join(CSVDecision2.root, 'spec/data/valid'))
|
7
7
|
|
8
8
|
it "loads all valid CSV files in the directory" do
|
9
|
-
tables =
|
9
|
+
tables = CSVDecision2.load(path, first_match: false, regexp_implicit: true)
|
10
10
|
expect(tables).to be_a Hash
|
11
11
|
expect(tables.count).to eq Dir[path.join('*.csv')].count
|
12
12
|
|
13
13
|
tables.each_pair do |name, table|
|
14
14
|
expect(name).to be_a(Symbol)
|
15
|
-
expect(table).to be_a(
|
15
|
+
expect(table).to be_a(CSVDecision2::Table)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
it 'rejects an invalid path name' do
|
20
|
-
expect {
|
20
|
+
expect { CSVDecision2.load('path') }
|
21
21
|
.to raise_error(ArgumentError, 'path argument must be a Pathname')
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'rejects an invalid folder name' do
|
25
|
-
expect {
|
25
|
+
expect { CSVDecision2.load(Pathname('path')) }
|
26
26
|
.to raise_error(ArgumentError, 'path argument not a valid folder')
|
27
27
|
end
|
28
|
-
end
|
28
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../../lib/
|
3
|
+
require_relative '../../../lib/csv_decision2'
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe CSVDecision2::Matchers::Function do
|
6
6
|
subject { described_class.new }
|
7
7
|
|
8
8
|
describe '#new' do
|
9
|
-
it { is_expected.to be_a
|
10
|
-
it { is_expected.to be_a
|
9
|
+
it { is_expected.to be_a CSVDecision2::Matchers::Function }
|
10
|
+
it { is_expected.to be_a CSVDecision2::Matchers::Matcher }
|
11
11
|
it { is_expected.to respond_to(:matches?).with(1).argument }
|
12
12
|
end
|
13
13
|
|
@@ -21,7 +21,7 @@ describe CSVDecision::Matchers::Function do
|
|
21
21
|
}
|
22
22
|
cells.each_pair do |cell, expected|
|
23
23
|
it "recognises #{cell} as a function" do
|
24
|
-
match =
|
24
|
+
match = CSVDecision2::Matchers::Function::FUNCTION_RE.match(cell)
|
25
25
|
expect(match['operator']).to eq expected[:operator]
|
26
26
|
expect(match['name']).to eq expected[:name]
|
27
27
|
end
|
@@ -63,7 +63,7 @@ describe CSVDecision::Matchers::Function do
|
|
63
63
|
# examples.each do |ex|
|
64
64
|
# it "cell #{ex[:cell]} matches value: #{ex[:value]} to hash: #{ex[:hash]}" do
|
65
65
|
# proc = matcher.matches?(ex[:cell])
|
66
|
-
# expect(proc).to be_a(
|
66
|
+
# expect(proc).to be_a(CSVDecision2::Proc)
|
67
67
|
# expect(proc.function.call(ex[:value], ex[:hash])).to eq ex[:result]
|
68
68
|
# end
|
69
69
|
# end
|
@@ -79,4 +79,4 @@ describe CSVDecision::Matchers::Function do
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
82
|
-
end
|
82
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../../lib/
|
3
|
+
require_relative '../../../lib/csv_decision2'
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe CSVDecision2::Matchers::Guard do
|
6
6
|
subject { described_class.new }
|
7
7
|
|
8
8
|
describe '#new' do
|
9
|
-
it { is_expected.to be_a
|
10
|
-
it { is_expected.to be_a
|
9
|
+
it { is_expected.to be_a CSVDecision2::Matchers::Guard }
|
10
|
+
it { is_expected.to be_a CSVDecision2::Matchers::Matcher }
|
11
11
|
it { is_expected.to respond_to(:matches?).with(1).argument }
|
12
12
|
end
|
13
13
|
|
@@ -116,7 +116,7 @@ describe CSVDecision::Matchers::Guard do
|
|
116
116
|
examples.each do |ex|
|
117
117
|
it "cell #{ex[:cell]} matches to hash: #{ex[:hash]}" do
|
118
118
|
proc = matcher.matches?(ex[:cell])
|
119
|
-
expect(proc).to be_a(
|
119
|
+
expect(proc).to be_a(CSVDecision2::Matchers::Proc)
|
120
120
|
expect(proc.type).to eq :guard
|
121
121
|
expect(proc.function.call(ex[:hash])).to eq ex[:result]
|
122
122
|
end
|
@@ -145,8 +145,8 @@ describe CSVDecision::Matchers::Guard do
|
|
145
145
|
DATA
|
146
146
|
|
147
147
|
specify do
|
148
|
-
expect {
|
149
|
-
.to raise_error(
|
148
|
+
expect { CSVDecision2.parse(data) }
|
149
|
+
.to raise_error(CSVDecision2::CellValidationError, 'guard: column cannot contain constants')
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
@@ -154,17 +154,17 @@ describe CSVDecision::Matchers::Guard do
|
|
154
154
|
data = <<~DATA
|
155
155
|
IN :country, guard : country, out :PAID, out :PAID_type, if:
|
156
156
|
US, :CUSIP.present?, :CUSIP, CUSIP, TRUE
|
157
|
-
GB, :SEDOL.present?, :SEDOL, SEDOL,
|
158
|
-
, :ISIN.present?, :ISIN, ISIN,
|
159
|
-
, :SEDOL.present?, :SEDOL, SEDOL,
|
160
|
-
, :CUSIP.present?, :CUSIP, CUSIP,
|
157
|
+
GB, :SEDOL.present?, :SEDOL, SEDOL,
|
158
|
+
, :ISIN.present?, :ISIN, ISIN,
|
159
|
+
, :SEDOL.present?, :SEDOL, SEDOL,
|
160
|
+
, :CUSIP.present?, :CUSIP, CUSIP,
|
161
161
|
, := nil, := nil, MISSING, := nil
|
162
162
|
DATA
|
163
163
|
|
164
164
|
specify do
|
165
|
-
expect {
|
166
|
-
.to raise_error(
|
165
|
+
expect { CSVDecision2.parse(data) }
|
166
|
+
.to raise_error(CSVDecision2::CellValidationError, 'if: column cannot contain constants')
|
167
167
|
end
|
168
168
|
end
|
169
169
|
end
|
170
|
-
end
|
170
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../../lib/
|
3
|
+
require_relative '../../../lib/csv_decision2'
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe CSVDecision2::Matchers::Numeric do
|
6
6
|
subject { described_class.new }
|
7
7
|
|
8
8
|
describe '#new' do
|
9
|
-
it { is_expected.to be_a
|
9
|
+
it { is_expected.to be_a CSVDecision2::Matchers::Numeric }
|
10
10
|
it { is_expected.to respond_to(:matches?).with(1).argument }
|
11
11
|
end
|
12
12
|
|
@@ -27,7 +27,7 @@ describe CSVDecision::Matchers::Numeric do
|
|
27
27
|
data.each do |cell, value|
|
28
28
|
it "comparision #{cell} matches #{value}" do
|
29
29
|
proc = matcher.matches?(cell)
|
30
|
-
expect(proc).to be_a(
|
30
|
+
expect(proc).to be_a(CSVDecision2::Matchers::Proc)
|
31
31
|
expect(proc.type).to eq :proc
|
32
32
|
expect(proc.function[value]).to eq true
|
33
33
|
end
|
@@ -44,4 +44,4 @@ describe CSVDecision::Matchers::Numeric do
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
|
-
end
|
47
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../../lib/
|
3
|
+
require_relative '../../../lib/csv_decision2'
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe CSVDecision2::Matchers::Pattern do
|
6
6
|
subject { described_class.new }
|
7
7
|
|
8
8
|
describe '#new' do
|
9
|
-
it { is_expected.to be_a
|
9
|
+
it { is_expected.to be_a CSVDecision2::Matchers::Pattern }
|
10
10
|
it { is_expected.to respond_to(:matches?).with(1).argument }
|
11
11
|
end
|
12
12
|
|
@@ -27,7 +27,7 @@ describe CSVDecision::Matchers::Pattern do
|
|
27
27
|
expressions.each do |cell|
|
28
28
|
it "recognises regexp #{cell}" do
|
29
29
|
proc = matcher.matches?(cell)
|
30
|
-
expect(proc).to be_a
|
30
|
+
expect(proc).to be_a CSVDecision2::Matchers::Proc
|
31
31
|
expect(proc.type).to eq :proc
|
32
32
|
expect(proc.function).to be_a ::Proc
|
33
33
|
expect(proc.function.arity).to eq -1
|
@@ -50,7 +50,7 @@ describe CSVDecision::Matchers::Pattern do
|
|
50
50
|
expressions.each do |cell|
|
51
51
|
it "recognises regexp #{cell}" do
|
52
52
|
proc = matcher.matches?(cell)
|
53
|
-
expect(proc).to be_a
|
53
|
+
expect(proc).to be_a CSVDecision2::Matchers::Proc
|
54
54
|
expect(proc.type).to eq :proc
|
55
55
|
expect(proc.function).to be_a ::Proc
|
56
56
|
expect(proc.function.arity).to eq -1
|
@@ -180,4 +180,4 @@ describe CSVDecision::Matchers::Pattern do
|
|
180
180
|
end
|
181
181
|
end
|
182
182
|
end
|
183
|
-
end
|
183
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../../lib/
|
3
|
+
require_relative '../../../lib/csv_decision2'
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe CSVDecision2::Matchers::Range do
|
6
6
|
subject { described_class.new }
|
7
7
|
|
8
8
|
describe '#new' do
|
9
|
-
it { is_expected.to be_a
|
9
|
+
it { is_expected.to be_a CSVDecision2::Matchers::Range }
|
10
10
|
it { is_expected.to respond_to(:matches?).with(1).argument }
|
11
11
|
end
|
12
12
|
|
@@ -29,7 +29,7 @@ describe CSVDecision::Matchers::Range do
|
|
29
29
|
data.each do |cell, value|
|
30
30
|
it "range #{cell} matches #{value}" do
|
31
31
|
proc = matcher.matches?(cell)
|
32
|
-
expect(proc).to be_a(
|
32
|
+
expect(proc).to be_a(CSVDecision2::Matchers::Proc)
|
33
33
|
expect(proc.type).to eq :proc
|
34
34
|
expect(proc.function[value]).to eq true
|
35
35
|
end
|
@@ -50,7 +50,7 @@ describe CSVDecision::Matchers::Range do
|
|
50
50
|
data.each do |cell, value|
|
51
51
|
it "range #{cell} does not match #{value}" do
|
52
52
|
proc = matcher.matches?(cell)
|
53
|
-
expect(proc).to be_a(
|
53
|
+
expect(proc).to be_a(CSVDecision2::Matchers::Proc)
|
54
54
|
expect(proc.type).to eq :proc
|
55
55
|
expect(proc.function[value]).to eq false
|
56
56
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../../lib/
|
3
|
+
require_relative '../../../lib/csv_decision2'
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe CSVDecision2::Matchers::Symbol do
|
6
6
|
subject { described_class.new }
|
7
7
|
|
8
8
|
describe '#new' do
|
9
|
-
it { is_expected.to be_a
|
10
|
-
it { is_expected.to be_a
|
9
|
+
it { is_expected.to be_a CSVDecision2::Matchers::Symbol }
|
10
|
+
it { is_expected.to be_a CSVDecision2::Matchers::Matcher }
|
11
11
|
it { is_expected.to respond_to(:matches?).with(1).argument }
|
12
12
|
end
|
13
13
|
|
@@ -48,7 +48,7 @@ describe CSVDecision::Matchers::Symbol do
|
|
48
48
|
examples.each do |ex|
|
49
49
|
it "cell #{ex[:cell]} matches value: #{ex[:value]} to hash: #{ex[:hash]}" do
|
50
50
|
proc = matcher.matches?(ex[:cell])
|
51
|
-
expect(proc).to be_a(
|
51
|
+
expect(proc).to be_a(CSVDecision2::Matchers::Proc)
|
52
52
|
expect(proc.function.call(ex[:value], ex[:hash])).to eq ex[:result]
|
53
53
|
end
|
54
54
|
end
|
@@ -64,4 +64,4 @@ describe CSVDecision::Matchers::Symbol do
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
67
|
-
end
|
67
|
+
end
|
@@ -1,24 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../lib/
|
3
|
+
require_relative '../../lib/csv_decision2'
|
4
4
|
|
5
|
-
SPEC_DATA_VALID ||= File.join(
|
6
|
-
SPEC_DATA_INVALID ||= File.join(
|
5
|
+
SPEC_DATA_VALID ||= File.join(CSVDecision2.root, 'spec', 'data', 'valid')
|
6
|
+
SPEC_DATA_INVALID ||= File.join(CSVDecision2.root, 'spec', 'data', 'invalid')
|
7
7
|
|
8
|
-
describe
|
8
|
+
describe CSVDecision2::Options do
|
9
9
|
it 'sets the default options' do
|
10
10
|
data = <<~DATA
|
11
11
|
IN :input, OUT :output
|
12
12
|
input0, output0
|
13
13
|
DATA
|
14
14
|
|
15
|
-
result =
|
15
|
+
result = CSVDecision2.parse(data)
|
16
16
|
|
17
17
|
expected = {
|
18
18
|
first_match: true,
|
19
19
|
regexp_implicit: false,
|
20
20
|
text_only: false,
|
21
|
-
matchers:
|
21
|
+
matchers: CSVDecision2::Options::DEFAULT_MATCHERS
|
22
22
|
}
|
23
23
|
expect(result.options).to eql expected
|
24
24
|
end
|
@@ -29,15 +29,15 @@ describe CSVDecision::Options do
|
|
29
29
|
input0, output0
|
30
30
|
DATA
|
31
31
|
|
32
|
-
result =
|
32
|
+
result = CSVDecision2.parse(data,
|
33
33
|
first_match: false,
|
34
|
-
matchers: [
|
34
|
+
matchers: [CSVDecision2::Matchers::Pattern])
|
35
35
|
|
36
36
|
expected = {
|
37
37
|
first_match: false,
|
38
38
|
regexp_implicit: false,
|
39
39
|
text_only: false,
|
40
|
-
matchers: [
|
40
|
+
matchers: [CSVDecision2::Matchers::Pattern]
|
41
41
|
}
|
42
42
|
expect(result.options).to eql expected
|
43
43
|
end
|
@@ -48,47 +48,47 @@ describe CSVDecision::Options do
|
|
48
48
|
input0, output0
|
49
49
|
DATA
|
50
50
|
|
51
|
-
expect {
|
52
|
-
.to raise_error(
|
51
|
+
expect { CSVDecision2.parse(data, bad_option: false) }
|
52
|
+
.to raise_error(CSVDecision2::CellValidationError,
|
53
53
|
"invalid option(s) supplied: [:bad_option]")
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'parses options from a CSV file' do
|
57
57
|
file = Pathname(File.join(SPEC_DATA_VALID, 'options_in_file1.csv'))
|
58
|
-
result =
|
58
|
+
result = CSVDecision2.parse(file)
|
59
59
|
|
60
60
|
expected = {
|
61
61
|
first_match: false,
|
62
62
|
regexp_implicit: false,
|
63
63
|
text_only: false,
|
64
|
-
matchers:
|
64
|
+
matchers: CSVDecision2::Options::DEFAULT_MATCHERS
|
65
65
|
}
|
66
66
|
expect(result.options).to eql expected
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'options from the CSV file override method options' do
|
70
70
|
file = Pathname(File.join(SPEC_DATA_VALID, 'options_in_file2.csv'))
|
71
|
-
result =
|
71
|
+
result = CSVDecision2.parse(file, first_match: true, regexp_implicit: nil)
|
72
72
|
|
73
73
|
expected = {
|
74
74
|
first_match: false,
|
75
75
|
regexp_implicit: true,
|
76
76
|
text_only: false,
|
77
|
-
matchers:
|
77
|
+
matchers: CSVDecision2::Options::DEFAULT_MATCHERS
|
78
78
|
}
|
79
79
|
expect(result.options).to eql expected
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'parses index option from the CSV file' do
|
83
83
|
file = Pathname(File.join(SPEC_DATA_VALID, 'options_in_file3.csv'))
|
84
|
-
result =
|
84
|
+
result = CSVDecision2.parse(file)
|
85
85
|
|
86
86
|
expected = {
|
87
87
|
first_match: false,
|
88
88
|
regexp_implicit: true,
|
89
89
|
text_only: false,
|
90
|
-
matchers:
|
90
|
+
matchers: CSVDecision2::Options::DEFAULT_MATCHERS
|
91
91
|
}
|
92
92
|
expect(result.options).to eql expected
|
93
93
|
end
|
94
|
-
end
|
94
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../lib/csv_decision2'
|
4
|
+
|
5
|
+
describe CSVDecision2::Parse do
|
6
|
+
it 'rejects an empty decision table' do
|
7
|
+
expect { CSVDecision2.parse('') }
|
8
|
+
.to raise_error(CSVDecision2::TableValidationError,
|
9
|
+
'table has no header row')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'parses a decision table from a CSV file' do
|
13
|
+
file = Pathname(File.join(CSVDecision2.root, 'spec/data/valid', 'valid.csv'))
|
14
|
+
result = CSVDecision2.parse(file)
|
15
|
+
|
16
|
+
expected = [
|
17
|
+
['input', '']
|
18
|
+
]
|
19
|
+
|
20
|
+
expect(result).to be_a(CSVDecision2::Table)
|
21
|
+
expect(result.rows).to eq expected
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'it parses valid CSV files' do
|
25
|
+
Dir[File.join(CSVDecision2.root, 'spec/data/valid/*.csv')].each do |file_name|
|
26
|
+
pathname = Pathname(file_name)
|
27
|
+
|
28
|
+
it "loads CSV file: #{pathname.basename}" do
|
29
|
+
expect { CSVDecision2.parse(pathname) }.not_to raise_error
|
30
|
+
expect(CSVDecision2.parse(pathname)).to be_a CSVDecision2::Table
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'it rejects invalid CSV files' do
|
36
|
+
Dir[File.join(CSVDecision2.root, 'spec/data/invalid/*.csv')].each do |file_name|
|
37
|
+
pathname = Pathname(file_name)
|
38
|
+
|
39
|
+
it "rejects CSV file: #{pathname.basename}" do
|
40
|
+
expect { CSVDecision2.parse(pathname) }.to raise_error(CSVDecision2::FileError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|