array_logic 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/array_logic/rule.rb +20 -21
- data/lib/array_logic/version.rb +10 -5
- data/test/array_logic/rule_test.rb +6 -4
- metadata +2 -2
data/lib/array_logic/rule.rb
CHANGED
@@ -52,7 +52,11 @@ module ArrayLogic
|
|
52
52
|
|
53
53
|
private
|
54
54
|
def logic
|
55
|
-
|
55
|
+
begin
|
56
|
+
eval(expression)
|
57
|
+
rescue SyntaxError
|
58
|
+
raise "Unable to determine logic from this expression : #{expression}"
|
59
|
+
end
|
56
60
|
end
|
57
61
|
|
58
62
|
def match_ids(ids)
|
@@ -82,9 +86,9 @@ module ArrayLogic
|
|
82
86
|
end
|
83
87
|
|
84
88
|
def rule_processing_steps
|
85
|
-
replace_item(function_pattern, value_of_function_called_on_id_objects)
|
86
89
|
add_space_around_puctuation_characters
|
87
90
|
make_everything_lower_case
|
91
|
+
replace_item(function_pattern, build_logic_from_function_statement)
|
88
92
|
replace_logic_words_with_operators
|
89
93
|
replace_item(thing_id_pattern, ids_include_this_id)
|
90
94
|
replace_item(number_in_set_pattern, comparison_of_number_with_true_count)
|
@@ -117,34 +121,29 @@ module ArrayLogic
|
|
117
121
|
end
|
118
122
|
|
119
123
|
def function_pattern
|
120
|
-
|
124
|
+
function_name_pattern = array_functions.keys.join('|')
|
125
|
+
instance_function_pattern = '\w+[\?\!]?' # e.g. 'id', 'this!', 'that?', 'foo_bar'
|
126
|
+
comparison_pattern ='(==|[\<\>]=?|!=)\s*\d+(\.\d+)?' # e.g. '== 4.3', '> 4'
|
127
|
+
/(#{function_name_pattern})\(\s*\:(#{instance_function_pattern})\s*\)\s*(#{comparison_pattern})/
|
121
128
|
end
|
122
129
|
|
123
130
|
def array_functions
|
124
131
|
{
|
125
|
-
:sum => '
|
126
|
-
:average => 'reduce(
|
132
|
+
:sum => 'reduce(0){|sum,x| x.respond_to?(:to_f) ? sum + x.to_f : sum }',
|
133
|
+
:average => 'reduce(0){|sum,x| x.respond_to?(:to_f) ? sum + x.to_f : sum } / size',
|
127
134
|
:count => 'compact.size'
|
128
135
|
}
|
129
136
|
end
|
130
137
|
|
131
|
-
def
|
138
|
+
def build_logic_from_function_statement
|
132
139
|
lambda do |string|
|
133
|
-
|
134
|
-
values = things.collect &
|
135
|
-
numbers_booleans_or_nils?(values)
|
140
|
+
array_function, instance_function, comparison = function_pattern.match(string).to_a[1, 3]
|
141
|
+
values = things.collect &instance_function.to_sym
|
136
142
|
result = values.instance_eval(array_functions[array_function.to_sym])
|
137
|
-
"( #{result} #{
|
143
|
+
"( #{result} #{comparison} )"
|
138
144
|
end
|
139
145
|
end
|
140
146
|
|
141
|
-
def numbers_booleans_or_nils?(values)
|
142
|
-
errors = values.reject{|v| v.nil? || v.is_a?(Numeric) || !!v == v}
|
143
|
-
unless errors.empty?
|
144
|
-
raise "Values must be numbers or nils. The problem is here: #{errors.join(", ")}"
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
147
|
def processed_rule
|
149
148
|
@processed_rule ||= rule.clone
|
150
149
|
end
|
@@ -200,13 +199,13 @@ module ArrayLogic
|
|
200
199
|
def allowed_characters
|
201
200
|
{
|
202
201
|
:brackets => ['\(', '\)'],
|
203
|
-
:in_pattern =>
|
202
|
+
:in_pattern => '\d+\s+in',
|
204
203
|
:ids => [thing_id_pattern],
|
205
204
|
:logic_words => %w{and or not},
|
206
205
|
:logic_chrs => ['&&', '\|\|', '!'],
|
207
|
-
:commas =>
|
208
|
-
:white_space =>
|
209
|
-
:function_pattern =>
|
206
|
+
:commas => '\,',
|
207
|
+
:white_space => '\s',
|
208
|
+
:function_pattern => function_pattern
|
210
209
|
}
|
211
210
|
end
|
212
211
|
|
data/lib/array_logic/version.rb
CHANGED
@@ -1,24 +1,29 @@
|
|
1
1
|
module ArrayLogic
|
2
|
-
VERSION = "0.2.
|
2
|
+
VERSION = "0.2.2"
|
3
3
|
end
|
4
4
|
|
5
5
|
# History
|
6
6
|
# =======
|
7
7
|
#
|
8
|
+
# Version 0.2.2
|
9
|
+
# -------------
|
10
|
+
# Refactor to allow functions to be more flexible. That's is, to handle unexpected
|
11
|
+
# input, rather than just rejecting it.
|
12
|
+
#
|
8
13
|
# Version 0.2.1
|
9
|
-
#
|
14
|
+
# -------------
|
10
15
|
# Improved handling of errors in functions and add != operator
|
11
16
|
#
|
12
17
|
# Version 0.2.0
|
13
|
-
#
|
18
|
+
# -------------
|
14
19
|
# Adds functions: sum, count and average
|
15
20
|
#
|
16
21
|
# Version 0.1.2
|
17
|
-
#
|
22
|
+
# -------------
|
18
23
|
# Refactor to tidy up code and make private, rule methods that don't need exposing
|
19
24
|
#
|
20
25
|
#
|
21
26
|
# Version 0.1.1
|
22
|
-
#
|
27
|
+
# -------------
|
23
28
|
# Working version. No history before this point
|
24
29
|
#
|
@@ -298,10 +298,12 @@ module ArrayLogic
|
|
298
298
|
end
|
299
299
|
|
300
300
|
def test_function_with_object_method_that_does_not_return_number
|
301
|
-
@rule.rule = '
|
302
|
-
|
303
|
-
|
304
|
-
|
301
|
+
@rule.rule = 'average(:methods) == 0'
|
302
|
+
assert @rule.match(get_things([1, 2]))
|
303
|
+
@rule.rule = 'sum(:methods) == 0'
|
304
|
+
assert @rule.match(get_things([1, 2]))
|
305
|
+
@rule.rule = 'count(:methods) == 2'
|
306
|
+
assert @rule.match(get_things([1, 2]))
|
305
307
|
end
|
306
308
|
|
307
309
|
def test_match_without_rule
|
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.2.
|
4
|
+
version: 0.2.2
|
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-03-
|
12
|
+
date: 2013-03-28 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.
|