active_redis 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 045f4c85e0aeb767fd6391f797427c932771c9b7
4
- data.tar.gz: 9e250673aa1a847c1bdd33a1f85550ea9cedc8e1
3
+ metadata.gz: 15b35e41e228279d6ebc16ce99d25115d786074f
4
+ data.tar.gz: 150c894dcd3e562549d4ee6a52a005020f262cc5
5
5
  SHA512:
6
- metadata.gz: 3f54e5432066d8cd19c9844e84dc37b68d4a15bc02c2b13dc7ee618a9934c0edae3aa23685f835a45fdf69dd50b01ed64e20f6bbb41916da8f417a400c26961b
7
- data.tar.gz: 91f1c901ff380025adc212ff0adb214d7f2c6577cffbd0017f3cf4f99752d4c4ded90efd9a74112cbad9350315f66421fd9a6b502b65b0df5faed39bbd7c3598
6
+ metadata.gz: 288bb1c18077d83a21a80d846d520f5a9f0539a31ce9dfeb24c76bf64d4b5c90a9adac9fcb69e601c2c9a2ca43724ad8c6266a9a714eb44301802bff56f7906d
7
+ data.tar.gz: fa32af2552935029c263779f957a592fe29763ac7d997ea10a5b2c5ec53e4c755d3f2753f4ea52452939381a9a2044d25d94a5107b15dccd0784de84c08e5827
data/README.md CHANGED
@@ -140,6 +140,10 @@ Method chaining. Now you may calling __where__, __order__, __limit__ something l
140
140
  Article.where(title: "Article title").where(views: 1000).order(title: :asc).limit(per_page: 20, page: 3)
141
141
  ```
142
142
 
143
+ ## NEW IN VERSION 0.0.8
144
+
145
+ Using aggregation functions with method chaining functional.
146
+
143
147
  ## Contributing
144
148
 
145
149
  1. Fork it
@@ -22,7 +22,7 @@ module ActiveRedis::ConnectionExt
22
22
  run_eval :where, [model.key_name], params.flatten
23
23
  end
24
24
 
25
- def run_query_analyzer(model, params = ["", "", ""])
25
+ def run_query_analyzer(model, params = ["", "", "", ""])
26
26
  run_eval :query_analyzer, [model.key_name, Time.now.to_i], params
27
27
  end
28
28
 
@@ -9,5 +9,9 @@ module ActiveRedis
9
9
 
10
10
  ASSOCIATIONS = [:has_one, :has_many, :belongs_to]
11
11
 
12
+ RELATION_METHODS = %w{where order limit first all}
13
+
14
+ QUERY_METHODS = CALCULATION_METHODS + RELATION_METHODS
15
+
12
16
  end
13
17
  end
@@ -131,11 +131,11 @@ local fetch_row = function(key, id)
131
131
  return redis.call("HGETALL", name)
132
132
  end
133
133
 
134
- -- Query analyzer for searching
134
+ -- Fetching objects collection by query params
135
135
  --
136
136
  -- key - table name
137
- -- argv - array with query parameters WHERE, ORDER, LIMIT
138
- local query_analyzer = function (keys, argv)
137
+ -- argv - array with query params
138
+ local fetch_collection = function(keys, argv)
139
139
  local temp_list = apply_where(keys[1], argv[1], tonumber(keys[2]))
140
140
  local sort_command = {"SORT", temp_list}
141
141
  sort_command = apply_order(keys[1], sort_command, argv[2])
@@ -147,3 +147,109 @@ local query_analyzer = function (keys, argv)
147
147
  end
148
148
  return result
149
149
  end
150
+
151
+ -- Fetching value from record by field name
152
+ --
153
+ -- record - record array
154
+ -- field - field name
155
+ local fetch_value_by_field = function(record, field)
156
+ for i = 1, #record, 2 do
157
+ if record[i] == field then
158
+ return record[i+1]
159
+ end
160
+ end
161
+ return ""
162
+ end
163
+
164
+ -- Fetching values from specified field to array
165
+ --
166
+ -- collection - array of objects
167
+ -- param - field name
168
+ local fetch_field_values_array = function(collection, field)
169
+ local result = {}
170
+ for index, record in pairs(collection) do
171
+ table.insert(result, fetch_value_by_field(record, param))
172
+ end
173
+ return result
174
+ end
175
+
176
+ local aggregation_functions = {
177
+ -- Applying count aggregation function
178
+ --
179
+ -- collection - array of objects for processing
180
+ -- param - particular param for aggregation function
181
+ aggregation_count = function(collection, param)
182
+ return #collection
183
+ end,
184
+
185
+ -- Applying sum aggregation function
186
+ --
187
+ -- collection - array of objects for processing
188
+ -- param - particular param for aggregation function
189
+ aggregation_sum = function(collection, param)
190
+ local sum = 0
191
+ for index, record in pairs(collection) do
192
+ sum = sum + tonumber(fetch_value_by_field(record, param))
193
+ end
194
+ return sum
195
+ end,
196
+
197
+ -- Applying pluck aggregation function
198
+ --
199
+ -- collection - array of objects for processing
200
+ -- param - particular param for aggregation function
201
+ aggregation_pluck = function(collection, param)
202
+ return fetch_field_values_array(collection, param)
203
+ end,
204
+
205
+ -- Applying min aggregation function
206
+ --
207
+ -- collection - array of objects for processing
208
+ -- param - particular param for aggregation function
209
+ aggregation_min = function(collection, param)
210
+ local result = fetch_field_values_array(collection, param)
211
+ table.sort(result)
212
+ return result[1]
213
+ end,
214
+
215
+ -- Applying max aggregation function
216
+ --
217
+ -- collection - array of objects for processing
218
+ -- param - particular param for aggregation function
219
+ aggregation_max = function(collection, param)
220
+ local result = fetch_field_values_array(collection, param)
221
+ table.sort(result)
222
+ return result[#result]
223
+ end
224
+ }
225
+
226
+ -- Applying aggregation functions to collection
227
+ --
228
+ -- collection - array of objects for processing
229
+ -- aggr_options - string with aggregation information
230
+ local process_aggregation = function(collection, aggr_options)
231
+ local aggr_arr = split(aggr_options, "=")
232
+ local aggr_function_name = "aggregation_"..aggr_arr[1]
233
+ --return _G[aggr_function_name](collection, aggr_arr[2])
234
+ return aggregation_functions[aggr_function_name](collection, aggr_arr[2])
235
+ end
236
+
237
+ -- Checking if query is single value
238
+ --
239
+ -- argv - array with query parameters
240
+ local is_single_value_query = function(argv)
241
+ return string.len(argv[4]) ~= 0
242
+ end
243
+
244
+ -- Query analyzer for searching
245
+ --
246
+ -- key - table name
247
+ -- argv - array with query parameters WHERE, ORDER, LIMIT, AGGREGATION
248
+ local query_analyzer = function (keys, argv)
249
+ local collection = fetch_collection(keys, argv)
250
+ if is_single_value_query(argv) == true then
251
+ return process_aggregation(collection, argv[4])
252
+ else
253
+ return collection
254
+ end
255
+ end
@@ -1,5 +1,6 @@
1
1
  require 'active_redis/relation'
2
2
  require 'active_redis/query_iterator'
3
+ require 'active_redis/constants'
3
4
 
4
5
  module ActiveRedis
5
6
  autoload :QueryExecutor, 'active_redis/query_executor'
@@ -8,10 +9,13 @@ module ActiveRedis
8
9
  include Relation
9
10
  include QueryIterator
10
11
 
12
+ attr_reader :where_options, :order_options, :limit_options, :aggregation_options, :target
13
+
11
14
  def initialize(target)
12
15
  @where_options = {}
13
16
  @order_options = {id: :asc}
14
- @limit_options = {per_page: 10, page: 0}
17
+ @limit_options = {}
18
+ @aggregation_options = {}
15
19
  @target = target
16
20
  end
17
21
 
@@ -26,14 +30,24 @@ module ActiveRedis
26
30
  end
27
31
 
28
32
  def apply_limit(options)
29
- @limit_options = options if options.any?
33
+ @limit_options = options
30
34
  self
31
35
  end
32
36
 
33
- def apply_top(options)
37
+ def apply_first(options)
34
38
  apply_limit per_page: 1, page: 0
35
39
  end
36
40
 
41
+ def apply_all(options)
42
+ apply_limit Hash.new
43
+ end
44
+
45
+ ActiveRedis::Constants::CALCULATION_METHODS.each do |method|
46
+ define_method "apply_#{method}" do |field|
47
+ apply_aggregation(method, field)
48
+ end
49
+ end
50
+
37
51
  def reload
38
52
  @collection = nil
39
53
  end
@@ -44,16 +58,21 @@ module ActiveRedis
44
58
 
45
59
  private
46
60
 
61
+ def apply_aggregation(type, field)
62
+ @aggregation_options = {type => field}
63
+ execute_query
64
+ end
65
+
47
66
  def execute_query
48
- QueryExecutor.execute(@target, @where_options, @order_options, @limit_options)
67
+ QueryExecutor.execute self
49
68
  end
50
69
 
51
70
  def objects_by_query
52
71
  res = execute_query.inject([]) { |arr, attrs| arr << @target.new(attrs) if attrs && attrs.any?; arr }
53
- top_limit? ? res.first : res
72
+ first_limit? ? res.first : res
54
73
  end
55
74
 
56
- def top_limit?
75
+ def first_limit?
57
76
  @limit_options[:per_page] == 1 && @limit_options[:page] == 0
58
77
  end
59
78
 
@@ -1,12 +1,16 @@
1
1
  module ActiveRedis
2
2
  class QueryExecutor
3
3
 
4
- def self.execute(target, where, order, limit)
5
- ActiveRedis.connection.run_query_analyzer target, [prepare_where(where), prepare_order(order), prepare_limit(limit)]
4
+ def self.execute(chainer)
5
+ ActiveRedis.connection.run_query_analyzer(chainer.target, prepare_params(chainer))
6
6
  end
7
7
 
8
8
  private
9
9
 
10
+ def self.prepare_params(chainer)
11
+ [prepare_where(chainer.where_options), prepare_order(chainer.order_options), prepare_limit(chainer.limit_options), prepare_aggregation(chainer.aggregation_options)]
12
+ end
13
+
10
14
  def self.prepare_where(where)
11
15
  where.keys.map{|key| "#{key}=#{where[key]}" }.join(",")
12
16
  end
@@ -20,5 +24,9 @@ module ActiveRedis
20
24
  limit.any? ? "#{limit[:page]}=#{limit[:per_page]}" : ""
21
25
  end
22
26
 
27
+ def self.prepare_aggregation(aggregation)
28
+ aggregation.inject("") {|str, (k, v)| str = "#{k}=#{v}" }
29
+ end
30
+
23
31
  end
24
32
  end
@@ -1,6 +1,5 @@
1
1
  module ActiveRedis
2
2
  module QueryIterator
3
- include Enumerable
4
3
 
5
4
  def method_missing(method, *args)
6
5
  unless linked_objects.is_a? Array
@@ -1,8 +1,10 @@
1
+ require 'active_redis/constants'
2
+
1
3
  module ActiveRedis
2
4
  autoload :QueryChainer, 'active_redis/query_chainer'
3
5
  module Relation
4
6
 
5
- %w{where order limit top}.each do |method|
7
+ ActiveRedis::Constants::QUERY_METHODS.each do |method|
6
8
  class_eval <<-CODE
7
9
  def #{method}(options = {})
8
10
  if self.class.name == "ActiveRedis::QueryChainer"
@@ -1,3 +1,3 @@
1
1
  module ActiveRedis
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Gernyak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-16 00:00:00.000000000 Z
11
+ date: 2013-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis