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.
@@ -52,7 +52,11 @@ module ArrayLogic
52
52
 
53
53
  private
54
54
  def logic
55
- eval(expression)
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
- /(#{array_functions.keys.join('|')})\(\s*\:(\w+[\?\!]?)\s*\)\s*((==|[\<\>\!]=?)\s*\d+(\.\d+)?)/
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 => 'inject(:+)',
126
- :average => 'reduce(:+) / size.to_f',
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 value_of_function_called_on_id_objects
138
+ def build_logic_from_function_statement
132
139
  lambda do |string|
133
- all, array_function, function, operator = function_pattern.match(string).to_a
134
- values = things.collect &function.to_sym
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} #{operator} )"
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 => ['\d+\s+in'],
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 => ['\s'],
209
- :function_pattern => [function_pattern]
206
+ :commas => '\,',
207
+ :white_space => '\s',
208
+ :function_pattern => function_pattern
210
209
  }
211
210
  end
212
211
 
@@ -1,24 +1,29 @@
1
1
  module ArrayLogic
2
- VERSION = "0.2.1"
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 = 'sum(:methods) == 1'
302
- assert_raise RuntimeError do
303
- @rule.match(get_things([1, 2]))
304
- end
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.1
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-27 00:00:00.000000000 Z
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.