array_logic 0.1.0 → 0.1.1
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/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
|