rudelo 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -7,5 +7,6 @@ gem 'rufus-decision', git: 'https://github.com/jmettraux/rufus-decision.git'
7
7
  # gem 'rufus-decision', git: 'https://github.com/lastobelus/rufus-decision.git', branch: 'short_circuit_matchers'
8
8
 
9
9
  group :development do
10
+ gem 'listen'
10
11
  gem "guard-rspec"
11
12
  end
data/README.md CHANGED
@@ -57,10 +57,11 @@ For a detailed description of the mini-language the set logic matcher uses, see
57
57
 
58
58
  ## Short-Circuiting
59
59
 
60
- The current released version of rufus-decision does not provide for matchers to shortcircuit. This can cause errors if you have a SetLogic matcher followed by a String matcher. I have a branch of rufus-decision that does short-circuiting that is pending review, if you need to use it add this to your Gemfile:
60
+ By default, Set Logic matchers short-circuit. That is to-say, if a cell does not match, the set logic matcher tells rufus-decision not to try any more matchers if the cell was valid set logic syntax. You can change this behaviour by setting ```matcher.short_circuit = false```
61
61
 
62
- ```gem 'rufus-decision', git: 'https://github.com/lastobelus/rufus-decision.git', branch: 'short_circuit_matchers'
63
- ```
62
+ ## Force Parsing
63
+
64
+ By default Set Logic matchers return false for ```matches?``` if they cannot parse a cell. Set ```matcher.force = true``` to force parsing and raise errors if a cell cannot be parsed.
64
65
 
65
66
  ## Contributing
66
67
 
data/SET_LOGIC_MATCHER.md CHANGED
@@ -1,3 +1,5 @@
1
+ * NOTE: optional space delimiter was removed *
2
+
1
3
  # Set Logic Matcher
2
4
 
3
5
  The SetLogic matcher allows a decision table cell to match based on set logic between the decision table and the corresponding entry in the hash being transformed.
@@ -9,13 +11,13 @@ When a decision table cell contains a set expression, the corresponding value in
9
11
 
10
12
  $(bob, mary) => Set["bob", "mary"]
11
13
  $(bob mary, jeff) => Set["bob mary", "jeff"]
12
- $('bob rob', jeff) => Set["bob rob", "jeff"]
14
+ $(bob rob, jeff) => Set["bob rob", "jeff"]
13
15
  ${r: ruby_code} => eval ruby code, ignoring unless it returns a set
14
16
  ${other_column} => apply set conversion to other_column
15
17
  $(${c1}, ${c2}) => Set["c1 contents", "c2 contents"]
16
18
  bob, mary => Set["bob", "mary"]
17
19
  bob mary => Set["bob mary"]
18
- 'bob, mary', jeff => Set["bob, mary", "jeff"]
20
+ "bob, mary", jeff => Set["bob, mary", "jeff"]
19
21
 
20
22
  ## Decision Table Cell Syntax
21
23
 
@@ -87,7 +89,7 @@ Set expressions can use the following operators:
87
89
 
88
90
  ## Examples
89
91
 
90
- $(bob jeff mary) & $in #= 2
92
+ $(bob, jeff, mary) & $in #= 2
91
93
  => does not match (bob, jeff, mary)
92
94
  => matches (bob, mary) or (jeff, mary) etc.
93
95
  => does not match (bob) or (jeff) or (mary)
@@ -29,17 +29,31 @@ module Rudelo
29
29
  module Matchers
30
30
  class SetLogic < Rufus::Decision::Matcher
31
31
  SYNTAX_EXPR = %r{\$\([^)]*\)|\$in}
32
+
33
+ # if true, will raise if a cell is not valid set logic syntax
32
34
  attr_accessor :force
35
+ attr_writer :short_circuit
36
+
37
+ def short_circuit
38
+ defined?(@short_circuit) ? @short_circuit : true
39
+ end
40
+
41
+ def return_on_cant_match
42
+ short_circuit ? :break : false
43
+ end
33
44
 
34
- def should_match?(cell, value)
45
+ def can_match?(cell)
35
46
  ! (cell =~ SYNTAX_EXPR).nil?
36
47
  end
37
48
 
38
49
  def matches?(cell, value)
50
+ puts "\n matches? `#{cell}` => `#{value}`"
51
+ return false unless force || can_match?(cell)
39
52
  evaluator = ast(cell)
40
- return false if evaluator.nil?
53
+ return return_on_cant_match if evaluator.nil?
41
54
  in_set = value_transform.apply(value_parser.parse(value)) unless in_set.is_a?(Set)
42
- ast(cell).eval(in_set)
55
+ result = evaluator.eval(in_set)
56
+ return result ? true : return_on_cant_match
43
57
  end
44
58
 
45
59
  def cell_substitution?
@@ -32,7 +32,7 @@ module Rudelo
32
32
  rule(:close_set) { str(')') }
33
33
 
34
34
  rule(:unquoted_element) {
35
- (close_set.absent? >> space.absent? >> comma.absent? >> any).
35
+ (close_set.absent? >> comma.absent? >> any).
36
36
  repeat(1).as(:element) }
37
37
  rule(:quoted_element) {
38
38
  (quote >>
@@ -40,7 +40,7 @@ module Rudelo
40
40
  as(:element) >>
41
41
  quote)}
42
42
  rule(:element) { quoted_element | unquoted_element }
43
- rule(:element_delimiter) { (comma | space) >> space? }
43
+ rule(:element_delimiter) { (comma) >> space? }
44
44
 
45
45
 
46
46
  rule(:bare_element_list) {
@@ -1,3 +1,3 @@
1
1
  module Rudelo
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.4"
3
3
  end
@@ -13,53 +13,53 @@ describe "Rudelo::Matchers::SetLogic" do
13
13
  end
14
14
 
15
15
  it "matches multiple values against multiple cells correctly" do
16
- cell1 = "$in same-as $(a b c)"
17
- cell2 = "$in same-as $(k f r)"
18
- expect(subject.matches?(cell1, 'a b c')).to be_true
19
- expect(subject.matches?(cell2, 'a b c')).to be_false
20
- expect(subject.matches?(cell1, 'k f r')).to be_false
21
- expect(subject.matches?(cell2, 'k f r')).to be_true
22
- expect(subject.matches?(cell1, 'a b c')).to be_true
23
- expect(subject.matches?(cell2, 'a b c')).to be_false
16
+ cell1 = "$in same-as $(a, b, c)"
17
+ cell2 = "$in same-as $(k, f, r)"
18
+ expect(subject.matches?(cell1, 'a,b,c')).to be_true
19
+ expect(subject.matches?(cell2, 'a,b,c')).to eq(:break)
20
+ expect(subject.matches?(cell1, 'k,f,r')).to eq(:break)
21
+ expect(subject.matches?(cell2, 'k,f,r')).to be_true
22
+ expect(subject.matches?(cell1, 'a,b,c')).to be_true
23
+ expect(subject.matches?(cell2, 'a,b,c')).to eq(:break)
24
24
  end
25
25
 
26
26
  context "rufus-decision" do
27
27
  let(:table){
28
28
  table = Rufus::Decision::Table.new(%{
29
- in:group, out:situation
30
- $(bob jeff mary alice ralph) & $in #= 2, company
31
- $(bob jeff mary alice ralph) & $in same-as $in #= 3, crowd
32
- $(bob jeff mary alice ralph) >= $in #> 3, exclusive-party
33
- $(bob jeff mary alice ralph) & $in < $in #> 5, PARTY!
34
- $(bob jeff mary alice ralph) & $in < $in #> 3, party
29
+ in:group, out:situation
30
+ "$(bob, jeff, mary, alice, ralph) & $in #= 2", company
31
+ "$(bob, jeff, mary, alice, ralph) & $in same-as $in #= 3", crowd
32
+ "$(bob, jeff, mary, alice, ralph) >= $in #> 3", exclusive-party
33
+ "$(bob, jeff, mary, alice, ralph) & $in < $in #> 5", PARTY!
34
+ "$(bob, jeff, mary, alice, ralph) & $in < $in #> 3", party
35
35
  })
36
36
  table.matchers.unshift Rudelo::Matchers::SetLogic.new
37
37
  table
38
38
  }
39
39
  it "transforms values" do
40
40
  expect(
41
- table.transform({'group' => "bob alice"})
42
- ).to eq({'group' => "bob alice", 'situation' => "company"})
41
+ table.transform({'group' => "bob, alice"})
42
+ ).to eq({'group' => "bob, alice", 'situation' => "company"})
43
43
 
44
44
  expect(
45
- table.transform({'group' => "bob alice jeff"})
46
- ).to eq({'group' => "bob alice jeff", 'situation' => "crowd"})
45
+ table.transform({'group' => "bob, alice, jeff"})
46
+ ).to eq({'group' => "bob, alice, jeff", 'situation' => "crowd"})
47
47
 
48
48
  expect(
49
- table.transform({'group' => "bob alice jeff ralph"})
50
- ).to eq({'group' => "bob alice jeff ralph", 'situation' => "exclusive-party"})
49
+ table.transform({'group' => "bob, alice, jeff, ralph"})
50
+ ).to eq({'group' => "bob, alice, jeff, ralph", 'situation' => "exclusive-party"})
51
51
 
52
52
  expect(
53
- table.transform({'group' => "bob alice jeff don"})
54
- ).to eq({'group' => "bob alice jeff don", 'situation' => "party"})
53
+ table.transform({'group' => "bob, alice, jeff, don"})
54
+ ).to eq({'group' => "bob, alice, jeff, don", 'situation' => "party"})
55
55
 
56
56
  expect(
57
- table.transform({'group' => "bob alice jeff mary ralph don"})
58
- ).to eq({'group' => "bob alice jeff mary ralph don", 'situation' => "PARTY!"})
57
+ table.transform({'group' => "bob, alice, jeff, mary, ralph, don"})
58
+ ).to eq({'group' => "bob, alice, jeff, mary, ralph, don", 'situation' => "PARTY!"})
59
59
 
60
60
  expect(
61
- table.transform({'group' => "bob alice jeff mary don bev"})
62
- ).to eq({'group' => "bob alice jeff mary don bev", 'situation' => "PARTY!"})
61
+ table.transform({'group' => "bob, alice, jeff, mary, don, bev"})
62
+ ).to eq({'group' => "bob, alice, jeff, mary, don, bev", 'situation' => "PARTY!"})
63
63
  end
64
64
  end
65
65
 
@@ -31,7 +31,7 @@ describe "Rudelo::Parsers::SetLogicParser" do
31
31
 
32
32
  it "parses set construction to an iterative operation list" do
33
33
 
34
- expect(expr_parser).to parse('$(bob mary) union $(ralph jeff) & $in', trace: true).as({
34
+ expect(expr_parser).to parse('$(bob, mary) union $(ralph, jeff) & $in', trace: true).as({
35
35
  :set_construction_expression=>{
36
36
  :left=>{:element_list=>[{:element=>"bob"}, {:element=>"mary"}] },
37
37
  :right=>[
@@ -68,7 +68,7 @@ describe "Rudelo::Parsers::SetLogicParser" do
68
68
  let(:expr_parser){ parser.set_logic_expression }
69
69
 
70
70
  it "parses set logic to a left-right tree" do
71
- expect(expr_parser).to parse('$(bob mary) < $(ralph jeff bob mary)', trace: true).as({
71
+ expect(expr_parser).to parse('$(bob, mary) < $(ralph, jeff, bob, mary)', trace: true).as({
72
72
  :set_logic_expression=>{
73
73
  :left=>{:element_list=>[
74
74
  {:element=>"bob"}, {:element=>"mary"}] },
@@ -80,7 +80,7 @@ describe "Rudelo::Parsers::SetLogicParser" do
80
80
  end
81
81
 
82
82
  it "parses the left hand side as a set construction expression" do
83
- expect(expr_parser).to parse('$(bob mary) union $in < $(ralph jeff bob mary)', trace: true).as({
83
+ expect(expr_parser).to parse('$(bob, mary) union $in < $(ralph, jeff, bob, mary)', trace: true).as({
84
84
  :set_logic_expression=>{
85
85
  :left=> {
86
86
  :set_construction_expression=>{
@@ -98,17 +98,17 @@ describe "Rudelo::Parsers::SetLogicParser" do
98
98
  end
99
99
 
100
100
  it "parses set logic ops in symbol form" do
101
- expect(expr_parser).to parse('$(bob mary) < $in', trace: true)
102
- expect(expr_parser).to parse('$(bob mary) <= $in', trace: true)
103
- expect(expr_parser).to parse('$(bob mary)>$in', trace: true)
104
- expect(expr_parser).to parse('$(bob mary) >= $in', trace: true)
101
+ expect(expr_parser).to parse('$(bob, mary) < $in', trace: true)
102
+ expect(expr_parser).to parse('$(bob, mary) <= $in', trace: true)
103
+ expect(expr_parser).to parse('$(bob, mary)>$in', trace: true)
104
+ expect(expr_parser).to parse('$(bob, mary) >= $in', trace: true)
105
105
  end
106
106
 
107
107
  it "parses set logic ops in word form" do
108
- expect(expr_parser).to parse('$in superset $(bob mary)', trace: true)
109
- expect(expr_parser).to parse('$in subset $(bob mary)', trace: true)
110
- expect(expr_parser).to parse('$in proper-superset $(bob mary)', trace: true)
111
- expect(expr_parser).to parse('$in proper-subset $(bob mary)', trace: true)
108
+ expect(expr_parser).to parse('$in superset $(bob, mary)', trace: true)
109
+ expect(expr_parser).to parse('$in subset $(bob, mary)', trace: true)
110
+ expect(expr_parser).to parse('$in proper-superset $(bob, mary)', trace: true)
111
+ expect(expr_parser).to parse('$in proper-subset $(bob, mary)', trace: true)
112
112
  end
113
113
 
114
114
  end
@@ -152,7 +152,7 @@ describe "Rudelo::Parsers::SetLogicTransform" do
152
152
 
153
153
  end
154
154
  context "with cardinality" do
155
- let(:expr){ "$(k z v) > $in #= 2" }
155
+ let(:expr){ "$(k, z, v) > $in #= 2" }
156
156
  it "transforms logic expression as match_expression.left" do
157
157
  expect(subject.left).to be_a_kind_of(
158
158
  Rudelo::Parsers::SetLogicTransform::SetLogicExpr)
@@ -166,7 +166,7 @@ describe "Rudelo::Parsers::SetLogicTransform" do
166
166
 
167
167
  context "construction expression" do
168
168
  context "alone" do
169
- let(:expr){ "$(k z v) + $in" }
169
+ let(:expr){ "$(k, z, v) + $in" }
170
170
  it "transforms construction expression as match_expression.left" do
171
171
  expect(subject.left).to be_a_kind_of(
172
172
  Rudelo::Parsers::SetLogicTransform::SetConstructionExpr)
@@ -178,7 +178,7 @@ describe "Rudelo::Parsers::SetLogicTransform" do
178
178
 
179
179
  end
180
180
  context "with cardinality" do
181
- let(:expr){ "$(k z v) + $in #= 2" }
181
+ let(:expr){ "$(k, z, v) + $in #= 2" }
182
182
  it "transforms construction expression as match_expression.left" do
183
183
  expect(subject.left).to be_a_kind_of(
184
184
  Rudelo::Parsers::SetLogicTransform::SetConstructionExpr)
@@ -201,11 +201,11 @@ describe "Rudelo::Parsers::SetLogicTransform" do
201
201
 
202
202
  context "cardinality examples" do
203
203
  specify{ expect(matching(
204
- '#= 2', in_set: %w{a b})).to be_true }
204
+ '#= 2', in_set: %w{a, b})).to be_true }
205
205
  specify{ expect(matching(
206
- '#< 3', in_set: %w{a b})).to be_true }
206
+ '#< 3', in_set: %w{a, b})).to be_true }
207
207
  specify{ expect(matching(
208
- '#> 1', in_set: %w{a b})).to be_true }
208
+ '#> 1', in_set: %w{a, b})).to be_true }
209
209
  specify{ expect(matching(
210
210
  '#= 3', in_set: %w{a b})).to be_false }
211
211
  specify{ expect(matching(
@@ -216,42 +216,42 @@ describe "Rudelo::Parsers::SetLogicTransform" do
216
216
 
217
217
  context "construction examples" do
218
218
  specify{ expect(matching(
219
- '$(a b c) & $in #= 2', in_set: %w{a b d})).to be_true }
219
+ '$(a, b, c) & $in #= 2', in_set: %w{a b d})).to be_true }
220
220
  specify{ expect(matching(
221
- '$(a b c) & $in', in_set: %w{a b d})).to be_true }
221
+ '$(a, b, c) & $in', in_set: %w{a b d})).to be_true }
222
222
  specify{ expect(matching(
223
- '$(a b c) & $in', in_set: %w{d e f})).to be_false }
223
+ '$(a, b, c) & $in', in_set: %w{d e f})).to be_false }
224
224
  specify{ expect(matching(
225
- '$(a b c) & $in #= 2', in_set: %w{a k d})).to be_false }
225
+ '$(a, b, c) & $in #= 2', in_set: %w{a k d})).to be_false }
226
226
  specify{ expect(matching(
227
- '$(a b c) + $in + $(e) #= 5', in_set: %w{b c d})).to be_true }
227
+ '$(a, b, c) + $in + $(e) #= 5', in_set: %w{b c d})).to be_true }
228
228
  end
229
229
 
230
230
  context "explicit set examples" do
231
231
  specify{ expect(matching(
232
- '$(a b c)', in_set: %w{a b})).to be_true }
232
+ '$(a, b, c)', in_set: %w{a b})).to be_true }
233
233
  specify{ expect(matching(
234
- '$(a b c)', in_set: %w{a k d})).to be_false }
234
+ '$(a, b, c)', in_set: %w{a k d})).to be_false }
235
235
  end
236
236
 
237
237
  context "logic examples" do
238
238
  specify{ expect(matching(
239
- '$(a b c) > $in', in_set: %w{a b})).to be_true }
239
+ '$(a, b, c) > $in', in_set: %w{a b})).to be_true }
240
240
  specify{ expect(matching(
241
- '$(a b c) > $in #=2', in_set: %w{a b})).to be_true }
241
+ '$(a, b, c) > $in #=2', in_set: %w{a b})).to be_true }
242
242
  specify{ expect(matching(
243
- '$(a b c) > $in #=1', in_set: %w{a})).to be_true }
243
+ '$(a, b, c) > $in #=1', in_set: %w{a})).to be_true }
244
244
  specify{ expect(matching(
245
- '$(a b c) ^ $in < $(a d k f)', in_set: %w{b c d})).to be_true }
245
+ '$(a, b, c) ^ $in < $(a, d, k, f)', in_set: %w{b c d})).to be_true }
246
246
  specify{ expect(matching(
247
- '$(a b c) ^ $in < $(a e k f)', in_set: %w{b c d})).to be_false }
247
+ '$(a, b, c) ^ $in < $(a, e, k, f)', in_set: %w{b c d})).to be_false }
248
248
  end
249
249
 
250
250
  context "using transform with multiple in-set values" do
251
251
  it "allows re-using a transform" do
252
252
  abc = Set.new(%w{a b c})
253
253
  efg = Set.new(%w{e f g})
254
- expr = '$in same-as $(a b c)'
254
+ expr = '$in same-as $(a, b, c)'
255
255
 
256
256
  transform = Rudelo::Parsers::SetLogicTransform.new(abc)
257
257
  ast = transform.apply(parser.parse(expr))
@@ -27,16 +27,13 @@ describe "Rudelo::Parsers::SetValueParser" do
27
27
  })
28
28
 
29
29
  expect(parser).to parse(%Q{bob mary}, trace: true).as({
30
- element_list: [
31
- {element: "bob"},
32
- {element: "mary"}
33
- ]
30
+ element_list:
31
+ {element: "bob mary"}
34
32
  })
35
33
 
36
34
  expect(parser).to parse(%Q{bob mary, ralph}, trace: true).as({
37
35
  element_list: [
38
- {element: "bob"},
39
- {element: "mary"},
36
+ {element: "bob mary"},
40
37
  {element: "ralph"}
41
38
  ]
42
39
  })
@@ -78,8 +75,7 @@ describe "Rudelo::Parsers::SetValueParser" do
78
75
  expect(parser).to parse(%Q{$("bob", mary jeff)}, trace: true).as({
79
76
  element_list: [
80
77
  {element: "bob"},
81
- {element: "mary"},
82
- {element: "jeff"},
78
+ {element: "mary jeff"},
83
79
  ]
84
80
  })
85
81
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rudelo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-22 00:00:00.000000000 Z
12
+ date: 2013-05-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rufus-decision
@@ -136,7 +136,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
136
136
  version: '0'
137
137
  segments:
138
138
  - 0
139
- hash: 3209606744768379856
139
+ hash: -283585303558073235
140
140
  required_rubygems_version: !ruby/object:Gem::Requirement
141
141
  none: false
142
142
  requirements:
@@ -145,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
145
  version: '0'
146
146
  segments:
147
147
  - 0
148
- hash: 3209606744768379856
148
+ hash: -283585303558073235
149
149
  requirements: []
150
150
  rubyforge_project:
151
151
  rubygems_version: 1.8.25