rudelo 0.2.3 → 0.2.4

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.
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