array_logic 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +10 -3
- data/lib/array_logic/rule.rb +36 -30
- data/lib/array_logic/version.rb +1 -1
- data/test/array_logic/rule_test.rb +55 -28
- data/test/array_logic/test_case.rb +2 -0
- metadata +8 -8
data/README.rdoc
CHANGED
@@ -29,6 +29,12 @@ The *match* and *matches* methods allow arrays to be tested against these rules:
|
|
29
29
|
rule_two.match([a1, a2]) --> false
|
30
30
|
rule_two.matches([a1, a2], [a1]) --> [[a1]]
|
31
31
|
|
32
|
+
You can also test for arrays that do not match the rule by using *block*
|
33
|
+
and *blockers*:
|
34
|
+
|
35
|
+
rule_two.block([a1, a2]) --> true
|
36
|
+
rule_two.blockers([a1, a2], [a1]) --> [[a1, a2]]
|
37
|
+
|
32
38
|
See test/array_logic/rule_test for more examples
|
33
39
|
|
34
40
|
=== Combinations that match
|
@@ -37,11 +43,12 @@ Two methods allow you to determine sample combinations that match the current
|
|
37
43
|
rule.
|
38
44
|
|
39
45
|
rule = ArrayLogic::Rule.new 'a1 and a2'
|
40
|
-
|
41
|
-
rule.
|
46
|
+
|
47
|
+
rule.matching_combinations --> [[1,2]]
|
48
|
+
rule.blocking_combinations --> [[1],[2]]
|
42
49
|
|
43
50
|
To limit the number of samples presented, both only use ids used within
|
44
|
-
the rule. For the example
|
51
|
+
the rule. For the example above, an array that includes [1,2] would match,
|
45
52
|
and so would [1,2,3]. However, arrays that only contain 1 or 2 would not match
|
46
53
|
(for example [1,3])
|
47
54
|
|
data/lib/array_logic/rule.rb
CHANGED
@@ -8,7 +8,11 @@ module ArrayLogic
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def matches(*array_of_things)
|
11
|
-
array_of_things.delete_if{|things|
|
11
|
+
array_of_things.delete_if{|things| block(things)}
|
12
|
+
end
|
13
|
+
|
14
|
+
def blockers(*array_of_things)
|
15
|
+
array_of_things.delete_if{|things| match(things)}
|
12
16
|
end
|
13
17
|
|
14
18
|
def match(things)
|
@@ -17,6 +21,10 @@ module ArrayLogic
|
|
17
21
|
@thing_ids = things.collect(&:id)
|
18
22
|
logic
|
19
23
|
end
|
24
|
+
|
25
|
+
def block(things)
|
26
|
+
! match(things)
|
27
|
+
end
|
20
28
|
|
21
29
|
def logic
|
22
30
|
eval(expression)
|
@@ -45,7 +53,12 @@ module ArrayLogic
|
|
45
53
|
def blocking_combinations
|
46
54
|
combinations_of_identifiers_in_rule_that_pass {|c| ! match_ids(c)}
|
47
55
|
end
|
48
|
-
|
56
|
+
|
57
|
+
def check_rule
|
58
|
+
check_rule_entered
|
59
|
+
check_allowed_characters
|
60
|
+
end
|
61
|
+
|
49
62
|
private
|
50
63
|
def match_ids(ids)
|
51
64
|
@thing_ids = ids
|
@@ -64,13 +77,6 @@ module ArrayLogic
|
|
64
77
|
object_ids_used.length
|
65
78
|
end
|
66
79
|
|
67
|
-
def combinations_of_identifiers_in_rule
|
68
|
-
ids = object_ids_used
|
69
|
-
combinations = Array.new
|
70
|
-
(1..ids.length).each{|n| ids.combination(n).each{|c| combinations << c}}
|
71
|
-
return combinations
|
72
|
-
end
|
73
|
-
|
74
80
|
def objects_identifiers_in_rule
|
75
81
|
rule_without_punctuation.split.delete_if{|x| !(thing_id_pattern =~ x)}
|
76
82
|
end
|
@@ -88,6 +94,7 @@ module ArrayLogic
|
|
88
94
|
replace_item(number_in_set_pattern, comparison_of_number_with_true_count)
|
89
95
|
end
|
90
96
|
|
97
|
+
# for example: 2 in t1, t2, t3
|
91
98
|
def number_in_set_pattern
|
92
99
|
/\d+\s+in\s+((true|false)[\,\s]*)+/
|
93
100
|
end
|
@@ -142,40 +149,39 @@ module ArrayLogic
|
|
142
149
|
def rule_without_punctuation
|
143
150
|
rule.gsub(/[[:punct:]]/, '')
|
144
151
|
end
|
145
|
-
|
146
|
-
def check_rule
|
147
|
-
check_rule_entered
|
148
|
-
check_allowed_characters
|
149
|
-
end
|
150
152
|
|
151
153
|
def check_rule_entered
|
152
154
|
raise "You must define a rule before trying to match" unless rule.kind_of? String
|
153
155
|
end
|
154
156
|
|
155
157
|
def check_allowed_characters
|
156
|
-
|
158
|
+
raise_invalid_characters unless allowed_characters_pattern =~ rule
|
157
159
|
end
|
160
|
+
|
161
|
+
def raise_invalid_characters
|
162
|
+
invalid = rule.split.collect{|s| (allowed_characters_pattern =~ s) ? nil : s }.compact
|
163
|
+
raise "The rule '#{rule}' is not valid. The problem is within '#{invalid.join(' ')}'"
|
164
|
+
end
|
158
165
|
|
159
|
-
def
|
166
|
+
def allowed_characters_pattern
|
160
167
|
case_insensitive = true
|
161
|
-
Regexp.new("^(#{
|
168
|
+
Regexp.new("^(#{array_of_allowed_patterns.join('|')})*$", case_insensitive)
|
162
169
|
end
|
163
170
|
|
164
171
|
def allowed_characters
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
172
|
+
{
|
173
|
+
:brackets => ['\(', '\)'],
|
174
|
+
:in_pattern => ['\d+\s+in'],
|
175
|
+
:ids => ['\w\d+'],
|
176
|
+
:logic_words => %w{and or not},
|
177
|
+
:logic_chrs => ['&&', '\|\|', '!'],
|
178
|
+
:commas => ['\,'],
|
179
|
+
:white_space => ['\s'],
|
180
|
+
}
|
174
181
|
end
|
175
|
-
|
176
|
-
def
|
177
|
-
|
178
|
-
raise "The rule '#{rule}' is not valid. The problem is within '#{invalid.join(' ')}'"
|
182
|
+
|
183
|
+
def array_of_allowed_patterns
|
184
|
+
allowed_characters.values.flatten
|
179
185
|
end
|
180
186
|
|
181
187
|
end
|
data/lib/array_logic/version.rb
CHANGED
@@ -158,6 +158,31 @@ module ArrayLogic
|
|
158
158
|
@rule.match([1, 2])
|
159
159
|
end
|
160
160
|
end
|
161
|
+
|
162
|
+
def test_match_with_empty_rule
|
163
|
+
@rule.rule = ""
|
164
|
+
things = get_things([1, 2])
|
165
|
+
assert(!@rule.match([things.first]), "Should be no match when rule empty")
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_block_without_rule
|
169
|
+
assert_raise RuntimeError do
|
170
|
+
@rule.block([1, 2])
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_block_with_number_rule
|
175
|
+
@rule.rule = 1
|
176
|
+
assert_raise RuntimeError do
|
177
|
+
@rule.block([1, 2])
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_block_with_empty_rule
|
182
|
+
@rule.rule = ""
|
183
|
+
things = get_things([1, 2])
|
184
|
+
assert(@rule.block([things.first]), "Should be block when rule empty")
|
185
|
+
end
|
161
186
|
|
162
187
|
def test_replace_item
|
163
188
|
@rule.rule = 't1 or ( t2 and t3 )'
|
@@ -180,46 +205,48 @@ module ArrayLogic
|
|
180
205
|
end
|
181
206
|
end
|
182
207
|
|
183
|
-
def
|
208
|
+
def test_matches_and_blokers
|
184
209
|
@rule.rule = 't1 and t2'
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
210
|
+
match_one = get_things [1, 2]
|
211
|
+
match_two = get_things [1, 2, 3]
|
212
|
+
no_match_one = get_things [2, 3]
|
213
|
+
no_match_two = get_things [3]
|
214
|
+
|
215
|
+
matches = @rule.matches(match_one, match_two, no_match_one, no_match_two)
|
216
|
+
expected_matches = [match_one, match_two]
|
217
|
+
assert_equal(expected_matches, matches, "Matches should be returned")
|
192
218
|
|
193
|
-
|
194
|
-
|
195
|
-
assert_equal(
|
219
|
+
blockers = @rule.blockers(match_one, match_two, no_match_one, no_match_two)
|
220
|
+
expected_blockers = [no_match_one, no_match_two]
|
221
|
+
assert_equal(expected_blockers, blockers, "Blockers should be returned")
|
196
222
|
end
|
197
223
|
|
198
|
-
def
|
224
|
+
def test_matches_and_blokers_with_or
|
199
225
|
@rule.rule = 't1 or t2'
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
226
|
+
match_one = get_things [1, 2]
|
227
|
+
match_two = get_things [1, 2, 3]
|
228
|
+
match_three = get_things [2, 3]
|
229
|
+
no_match_one = get_things [3]
|
230
|
+
|
231
|
+
matches = @rule.matches(match_one, match_two, match_three, no_match_one)
|
232
|
+
expected_matches = [match_one, match_two, match_three]
|
233
|
+
assert_equal(expected_matches, matches, "Matches should be returned")
|
207
234
|
|
208
|
-
|
209
|
-
|
210
|
-
assert_equal(
|
235
|
+
blockers = @rule.blockers(match_one, match_two, match_three, no_match_one)
|
236
|
+
expected_blockers = [no_match_one]
|
237
|
+
assert_equal(expected_blockers, blockers, "Blockers should be returned")
|
211
238
|
end
|
212
239
|
|
213
|
-
def
|
240
|
+
def test_matches_with_empty_rule
|
214
241
|
@rule.rule = ""
|
215
|
-
things = get_things([1, 2])
|
216
|
-
|
242
|
+
things = get_things([1, 2]).collect{|t| [t]}
|
243
|
+
assert_equal([], @rule.matches(*things))
|
217
244
|
end
|
218
245
|
|
219
|
-
def
|
246
|
+
def test_blokers_with_empty_rule
|
220
247
|
@rule.rule = ""
|
221
|
-
things = get_things([1, 2])
|
222
|
-
assert_equal(
|
248
|
+
things = get_things([1, 2]).collect{|t| [t]}
|
249
|
+
assert_equal(things, @rule.blockers(*things))
|
223
250
|
end
|
224
251
|
|
225
252
|
def test_object_ids_used
|
@@ -15,11 +15,13 @@ module ArrayLogic
|
|
15
15
|
def assert_thing_match(thing_ids, rule)
|
16
16
|
get_things(thing_ids)
|
17
17
|
assert(rule.match(@things), "#{thing_ids.inspect} should match '#{rule.rule}'")
|
18
|
+
assert(!rule.block(@things), "#{thing_ids.inspect} should not block '#{rule.rule}'")
|
18
19
|
end
|
19
20
|
|
20
21
|
def assert_no_thing_match(thing_ids, rule)
|
21
22
|
get_things(thing_ids)
|
22
23
|
assert(!rule.match(@things), "#{thing_ids.inspect} should not match '#{rule.rule}'")
|
24
|
+
assert(rule.block(@things), "#{thing_ids.inspect} should block '#{rule.rule}'")
|
23
25
|
end
|
24
26
|
end
|
25
27
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: array_logic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
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: 2012-12-
|
12
|
+
date: 2012-12-13 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Allow a user to define a set of rules, and then test to see if an array
|
15
15
|
of object match those rules.
|
@@ -19,17 +19,17 @@ executables: []
|
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
-
- lib/array_logic.rb
|
23
|
-
- lib/array_logic/thing.rb
|
24
22
|
- lib/array_logic/version.rb
|
23
|
+
- lib/array_logic/thing.rb
|
25
24
|
- lib/array_logic/rule.rb
|
25
|
+
- lib/array_logic.rb
|
26
26
|
- lib/example.rb
|
27
27
|
- MIT-LICENSE
|
28
28
|
- Rakefile
|
29
29
|
- README.rdoc
|
30
|
-
- test/array_logic/thing_test.rb
|
31
|
-
- test/array_logic/rule_test.rb
|
32
30
|
- test/array_logic/test_case.rb
|
31
|
+
- test/array_logic/rule_test.rb
|
32
|
+
- test/array_logic/thing_test.rb
|
33
33
|
homepage: https://github.com/reggieb/array_logic
|
34
34
|
licenses: []
|
35
35
|
post_install_message:
|
@@ -55,6 +55,6 @@ signing_key:
|
|
55
55
|
specification_version: 3
|
56
56
|
summary: Matches arrays of objects against logical rules.
|
57
57
|
test_files:
|
58
|
-
- test/array_logic/thing_test.rb
|
59
|
-
- test/array_logic/rule_test.rb
|
60
58
|
- test/array_logic/test_case.rb
|
59
|
+
- test/array_logic/rule_test.rb
|
60
|
+
- test/array_logic/thing_test.rb
|