redistat 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +5 -0
- data/lib/redistat.rb +4 -2
- data/lib/redistat/database.rb +1 -0
- data/lib/redistat/event.rb +12 -24
- data/lib/redistat/finder.rb +41 -31
- data/lib/redistat/key.rb +40 -21
- data/lib/redistat/label.rb +27 -16
- data/lib/redistat/model.rb +14 -39
- data/lib/redistat/options.rb +43 -0
- data/lib/redistat/summary.rb +13 -5
- data/lib/redistat/version.rb +1 -1
- data/redistat.gemspec +1 -0
- data/spec/event_spec.rb +4 -4
- data/spec/finder_spec.rb +42 -26
- data/spec/key_spec.rb +63 -12
- data/spec/label_spec.rb +28 -18
- data/spec/model_spec.rb +45 -8
- data/spec/options_spec.rb +36 -0
- data/spec/summary_spec.rb +5 -5
- metadata +22 -5
data/README.md
CHANGED
@@ -66,6 +66,11 @@ When retrieving statistics for a given date range, Redistat figures out how to d
|
|
66
66
|
* Anything else that becomes apparent after real-world use.
|
67
67
|
|
68
68
|
|
69
|
+
## Credits
|
70
|
+
|
71
|
+
[Global Personals](http://globalpersonals.co.uk/) deserves a thank you. Currently the primary user of Redistat, they've allowed me to spend some company time to further develop the project.
|
72
|
+
|
73
|
+
|
69
74
|
## Note on Patches/Pull Requests
|
70
75
|
|
71
76
|
* Fork the project.
|
data/lib/redistat.rb
CHANGED
@@ -9,9 +9,10 @@ require 'time_ext'
|
|
9
9
|
require 'json'
|
10
10
|
require 'digest/sha1'
|
11
11
|
|
12
|
-
require 'redistat/
|
12
|
+
require 'redistat/options'
|
13
13
|
require 'redistat/connection'
|
14
14
|
require 'redistat/database'
|
15
|
+
require 'redistat/collection'
|
15
16
|
require 'redistat/date'
|
16
17
|
require 'redistat/date_helper'
|
17
18
|
require 'redistat/event'
|
@@ -34,8 +35,9 @@ module Redistat
|
|
34
35
|
|
35
36
|
KEY_NEXT_ID = ".next_id"
|
36
37
|
KEY_EVENT = ".event:"
|
37
|
-
KEY_LEBELS = "Redistat.
|
38
|
+
KEY_LEBELS = "Redistat.labels:" # used for reverse label hash lookup
|
38
39
|
KEY_EVENT_IDS = ".event_ids"
|
40
|
+
LABEL_INDEX = ".label_index:"
|
39
41
|
GROUP_SEPARATOR = "/"
|
40
42
|
|
41
43
|
class InvalidOptions < ArgumentError; end
|
data/lib/redistat/database.rb
CHANGED
data/lib/redistat/event.rb
CHANGED
@@ -1,40 +1,28 @@
|
|
1
1
|
module Redistat
|
2
2
|
class Event
|
3
3
|
include Database
|
4
|
+
include Options
|
4
5
|
|
5
6
|
attr_reader :id
|
6
7
|
attr_reader :key
|
7
|
-
attr_reader :connection_ref
|
8
8
|
|
9
9
|
attr_accessor :stats
|
10
10
|
attr_accessor :meta
|
11
|
-
attr_accessor :options
|
12
11
|
|
13
|
-
def initialize(scope, label = nil, date = nil, stats = {}, options = {}, meta = {}, is_new = true)
|
14
|
-
@options = parse_options(options)
|
15
|
-
@connection_ref = @options[:connection_ref]
|
16
|
-
@key = Key.new(scope, label, date, @options)
|
17
|
-
@stats = stats ||= {}
|
18
|
-
@meta = meta ||= {}
|
19
|
-
@new = is_new
|
20
|
-
end
|
21
|
-
|
22
|
-
def db
|
23
|
-
super(@connection_ref)
|
24
|
-
end
|
25
|
-
|
26
|
-
def parse_options(options)
|
27
|
-
default_options.each do |opt, val|
|
28
|
-
options[opt] = val if options[opt].nil?
|
29
|
-
end
|
30
|
-
options
|
31
|
-
end
|
32
|
-
|
33
12
|
def default_options
|
34
13
|
{ :depth => :hour,
|
35
14
|
:store_event => false,
|
36
15
|
:connection_ref => nil,
|
37
|
-
:enable_grouping => true
|
16
|
+
:enable_grouping => true,
|
17
|
+
:label_indexing => true }
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(scope, label = nil, date = nil, stats = {}, opts = {}, meta = {}, is_new = true)
|
21
|
+
parse_options(opts)
|
22
|
+
@key = Key.new(scope, label, date, @options)
|
23
|
+
@stats = stats ||= {}
|
24
|
+
@meta = meta ||= {}
|
25
|
+
@new = is_new
|
38
26
|
end
|
39
27
|
|
40
28
|
def new?
|
@@ -75,7 +63,7 @@ module Redistat
|
|
75
63
|
|
76
64
|
def save
|
77
65
|
return false if !self.new?
|
78
|
-
Summary.update_all(@key, @stats, depth_limit, @
|
66
|
+
Summary.update_all(@key, @stats, depth_limit, @options)
|
79
67
|
if @options[:store_event]
|
80
68
|
@id = self.next_id
|
81
69
|
db.hmset("#{self.scope}#{KEY_EVENT}#{@id}",
|
data/lib/redistat/finder.rb
CHANGED
@@ -40,8 +40,12 @@ module Redistat
|
|
40
40
|
|
41
41
|
attr_reader :options
|
42
42
|
|
43
|
-
def initialize(
|
44
|
-
|
43
|
+
def initialize(opts = {})
|
44
|
+
set_options(opts)
|
45
|
+
end
|
46
|
+
|
47
|
+
def options
|
48
|
+
@options ||= {}
|
45
49
|
end
|
46
50
|
|
47
51
|
def all(reload = false)
|
@@ -65,21 +69,27 @@ module Redistat
|
|
65
69
|
all.each_with_index(&block)
|
66
70
|
end
|
67
71
|
|
72
|
+
def children
|
73
|
+
build_key.children.map { |key|
|
74
|
+
self.class.new(options.merge(:label => key.label.to_s))
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
68
78
|
def connection_ref(ref)
|
69
|
-
reset! if
|
70
|
-
|
79
|
+
reset! if options[:connection_ref] != ref
|
80
|
+
options[:connection_ref] = ref
|
71
81
|
self
|
72
82
|
end
|
73
83
|
|
74
84
|
def scope(scope)
|
75
|
-
reset! if
|
76
|
-
|
85
|
+
reset! if !options[:scope].nil? && options[:scope].to_s != scope
|
86
|
+
options[:scope] = Scope.new(scope)
|
77
87
|
self
|
78
88
|
end
|
79
89
|
|
80
90
|
def label(label)
|
81
|
-
reset! if
|
82
|
-
|
91
|
+
reset! if !options[:label].nil? && options[:label].to_s != label
|
92
|
+
options[:label] = Label.new(label)
|
83
93
|
self
|
84
94
|
end
|
85
95
|
|
@@ -89,34 +99,34 @@ module Redistat
|
|
89
99
|
alias :date :dates
|
90
100
|
|
91
101
|
def from(date)
|
92
|
-
reset! if
|
93
|
-
|
102
|
+
reset! if options[:from] != date
|
103
|
+
options[:from] = date
|
94
104
|
self
|
95
105
|
end
|
96
106
|
|
97
107
|
def till(date)
|
98
|
-
reset! if
|
99
|
-
|
108
|
+
reset! if options[:till] != date
|
109
|
+
options[:till] = date
|
100
110
|
self
|
101
111
|
end
|
102
112
|
alias :until :till
|
103
113
|
|
104
114
|
def depth(unit)
|
105
|
-
reset! if
|
106
|
-
|
115
|
+
reset! if options[:depth] != unit
|
116
|
+
options[:depth] = unit
|
107
117
|
self
|
108
118
|
end
|
109
119
|
|
110
120
|
def interval(unit)
|
111
|
-
reset! if
|
112
|
-
|
121
|
+
reset! if options[:interval] != unit
|
122
|
+
options[:interval] = unit
|
113
123
|
self
|
114
124
|
end
|
115
125
|
|
116
|
-
def find(
|
117
|
-
set_options(
|
126
|
+
def find(opts = {})
|
127
|
+
set_options(opts)
|
118
128
|
raise InvalidOptions.new if !valid_options?
|
119
|
-
if
|
129
|
+
if options[:interval].nil? || !options[:interval]
|
120
130
|
find_by_magic
|
121
131
|
else
|
122
132
|
find_by_interval
|
@@ -130,14 +140,14 @@ module Redistat
|
|
130
140
|
opts.each do |key, value|
|
131
141
|
self.send(key, opts.delete(key)) if self.respond_to?(key)
|
132
142
|
end
|
133
|
-
|
143
|
+
self.options.merge!(opts)
|
134
144
|
end
|
135
145
|
|
136
|
-
def find_by_interval
|
146
|
+
def find_by_interval
|
137
147
|
raise InvalidOptions.new if !valid_options?
|
138
148
|
key = build_key
|
139
|
-
col = Collection.new(
|
140
|
-
col.total = Result.new(
|
149
|
+
col = Collection.new(options)
|
150
|
+
col.total = Result.new(options)
|
141
151
|
build_date_sets.each do |set|
|
142
152
|
set[:add].each do |date|
|
143
153
|
result = Result.new
|
@@ -152,11 +162,11 @@ module Redistat
|
|
152
162
|
col
|
153
163
|
end
|
154
164
|
|
155
|
-
def find_by_magic
|
165
|
+
def find_by_magic
|
156
166
|
raise InvalidOptions.new if !valid_options?
|
157
|
-
key =
|
158
|
-
col = Collection.new(
|
159
|
-
col.total = Result.new(
|
167
|
+
key = build_key
|
168
|
+
col = Collection.new(options)
|
169
|
+
col.total = Result.new(options)
|
160
170
|
col << col.total
|
161
171
|
build_date_sets.each do |set|
|
162
172
|
sum = Result.new
|
@@ -174,16 +184,16 @@ module Redistat
|
|
174
184
|
end
|
175
185
|
|
176
186
|
def valid_options?
|
177
|
-
return true if
|
187
|
+
return true if !options[:scope].blank? && !options[:label].blank? && !options[:from].blank? && !options[:till].blank?
|
178
188
|
false
|
179
189
|
end
|
180
190
|
|
181
191
|
def build_date_sets
|
182
|
-
Finder::DateSet.new(
|
192
|
+
Finder::DateSet.new(options[:from], options[:till], options[:depth], options[:interval])
|
183
193
|
end
|
184
194
|
|
185
195
|
def build_key
|
186
|
-
Key.new(
|
196
|
+
Key.new(options[:scope], options[:label])
|
187
197
|
end
|
188
198
|
|
189
199
|
def summarize_add_keys(sets, key, sum)
|
@@ -205,7 +215,7 @@ module Redistat
|
|
205
215
|
end
|
206
216
|
|
207
217
|
def db
|
208
|
-
super(
|
218
|
+
super(options[:connection_ref])
|
209
219
|
end
|
210
220
|
|
211
221
|
end
|
data/lib/redistat/key.rb
CHANGED
@@ -1,24 +1,22 @@
|
|
1
1
|
module Redistat
|
2
2
|
class Key
|
3
|
+
include Database
|
4
|
+
include Options
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
-
|
6
|
+
def default_options
|
7
|
+
{ :depth => :hour }
|
8
|
+
end
|
7
9
|
|
8
|
-
def initialize(scope, label_name = nil, time_stamp = nil,
|
9
|
-
|
10
|
-
|
10
|
+
def initialize(scope, label_name = nil, time_stamp = nil, opts = {})
|
11
|
+
parse_options(opts)
|
12
|
+
self.scope = scope
|
11
13
|
self.label = label_name if !label_name.nil?
|
12
14
|
self.date = time_stamp ||= Time.now
|
13
15
|
end
|
14
16
|
|
15
|
-
def default_options
|
16
|
-
{ :depth => :hour, :hashed_label => false }
|
17
|
-
end
|
18
|
-
|
19
17
|
def prefix
|
20
18
|
key = "#{@scope}"
|
21
|
-
key << "/#{label}" if !label.nil?
|
19
|
+
key << "/#{label.name}" if !label.nil?
|
22
20
|
key << ":"
|
23
21
|
key
|
24
22
|
end
|
@@ -26,30 +24,51 @@ module Redistat
|
|
26
24
|
def date=(input)
|
27
25
|
@date = (input.instance_of?(Redistat::Date)) ? input : Date.new(input) # Redistat::Date, not ::Date
|
28
26
|
end
|
27
|
+
attr_reader :date
|
29
28
|
|
30
29
|
def depth
|
31
|
-
|
30
|
+
options[:depth]
|
31
|
+
end
|
32
|
+
|
33
|
+
def scope
|
34
|
+
@scope.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def scope=(input)
|
38
|
+
@scope = (input.instance_of?(Redistat::Scope)) ? input : Scope.new(input)
|
32
39
|
end
|
33
40
|
|
34
|
-
def label
|
35
|
-
@label.
|
41
|
+
def label=(input)
|
42
|
+
@label = (input.instance_of?(Redistat::Label)) ? input : Label.create(input, @options)
|
36
43
|
end
|
44
|
+
attr_reader :label
|
37
45
|
|
38
46
|
def label_hash
|
39
47
|
@label.hash
|
40
48
|
end
|
41
49
|
|
42
|
-
def
|
43
|
-
@label.
|
50
|
+
def parent
|
51
|
+
@parent ||= self.class.new(self.scope, @label.parent, self.date, @options) unless @label.parent.nil?
|
44
52
|
end
|
45
53
|
|
46
|
-
def
|
47
|
-
@label
|
54
|
+
def children
|
55
|
+
db.smembers("#{scope}#{LABEL_INDEX}#{@label}").map { |member|
|
56
|
+
child_label = [@label, member].reject { |i| i.nil? }
|
57
|
+
self.class.new(self.scope, child_label.join(GROUP_SEPARATOR), self.date, @options)
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def update_index
|
62
|
+
@label.groups.each do |label|
|
63
|
+
# break if label.parent.nil?
|
64
|
+
parent = (label.parent || "")
|
65
|
+
db.sadd("#{scope}#{LABEL_INDEX}#{parent}", label.me)
|
66
|
+
end
|
48
67
|
end
|
49
68
|
|
50
|
-
def groups
|
51
|
-
@groups ||=
|
52
|
-
self.class.new(@scope,
|
69
|
+
def groups # TODO: Is this useless?
|
70
|
+
@groups ||= @label.groups.map do |label|
|
71
|
+
self.class.new(@scope, label, self.date, @options)
|
53
72
|
end
|
54
73
|
end
|
55
74
|
|
data/lib/redistat/label.rb
CHANGED
@@ -1,48 +1,59 @@
|
|
1
1
|
module Redistat
|
2
2
|
class Label
|
3
3
|
include Database
|
4
|
+
include Options
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
def default_options
|
7
|
+
{ :hashed_label => false }
|
8
|
+
end
|
7
9
|
|
8
|
-
def self.create(name,
|
9
|
-
self.new(name,
|
10
|
+
def self.create(name, opts = {})
|
11
|
+
self.new(name, opts).save
|
10
12
|
end
|
11
13
|
|
12
|
-
def initialize(str,
|
13
|
-
|
14
|
+
def initialize(str, opts = {})
|
15
|
+
parse_options(opts)
|
14
16
|
@raw = str.to_s
|
15
17
|
end
|
16
|
-
|
17
|
-
def
|
18
|
-
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
@raw
|
19
21
|
end
|
20
22
|
|
21
23
|
def name
|
22
|
-
@options[:hashed_label] ? hash :
|
24
|
+
@options[:hashed_label] ? hash : self.to_s
|
23
25
|
end
|
24
26
|
|
25
27
|
def hash
|
26
|
-
@hash ||= Digest::SHA1.hexdigest(
|
28
|
+
@hash ||= Digest::SHA1.hexdigest(self.to_s)
|
27
29
|
end
|
28
30
|
|
29
31
|
def save
|
30
|
-
@saved =
|
32
|
+
@saved = db.hset(KEY_LEBELS, hash, self.to_s) if @options[:hashed_label]
|
31
33
|
self
|
32
34
|
end
|
33
35
|
|
34
36
|
def saved?
|
37
|
+
return true unless @options[:hashed_label]
|
35
38
|
@saved ||= false
|
36
39
|
end
|
37
40
|
|
41
|
+
def parent
|
42
|
+
@parent ||= groups[1] if groups.size > 1
|
43
|
+
end
|
44
|
+
|
45
|
+
def me
|
46
|
+
self.to_s.split(GROUP_SEPARATOR).last
|
47
|
+
end
|
48
|
+
|
38
49
|
def groups
|
39
|
-
return @groups
|
50
|
+
return @groups unless @groups.nil?
|
40
51
|
@groups = []
|
41
52
|
parent = ""
|
42
|
-
|
53
|
+
self.to_s.split(GROUP_SEPARATOR).each do |part|
|
43
54
|
if !part.blank?
|
44
|
-
group = ((parent.blank?) ? "" : "#{parent}
|
45
|
-
@groups << group
|
55
|
+
group = ((parent.blank?) ? "" : "#{parent}#{GROUP_SEPARATOR}") + part
|
56
|
+
@groups << Label.new(group)
|
46
57
|
parent = group
|
47
58
|
end
|
48
59
|
end
|
data/lib/redistat/model.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
module Redistat
|
2
2
|
module Model
|
3
|
-
include
|
3
|
+
include Database
|
4
|
+
include Options
|
4
5
|
|
5
6
|
def self.included(base)
|
6
7
|
base.extend(self)
|
7
8
|
end
|
8
9
|
|
10
|
+
|
9
11
|
#
|
10
12
|
# statistics store/fetch methods
|
11
13
|
#
|
12
14
|
|
13
|
-
def store(label, stats = {}, date = nil,
|
15
|
+
def store(label, stats = {}, date = nil, opts = {}, meta = {})
|
14
16
|
Event.new(name, label, date, stats, options.merge(opts), meta).save
|
15
17
|
end
|
16
18
|
alias :event :store
|
@@ -21,53 +23,30 @@ module Redistat
|
|
21
23
|
alias :lookup :fetch
|
22
24
|
|
23
25
|
def find(label, from, till, opts = {})
|
24
|
-
Finder.new( { :scope => name,
|
26
|
+
Finder.new( { :scope => self.name,
|
25
27
|
:label => label,
|
26
28
|
:from => from,
|
27
29
|
:till => till }.merge(options.merge(opts)) )
|
28
30
|
end
|
29
31
|
|
32
|
+
|
30
33
|
#
|
31
34
|
# options methods
|
32
35
|
#
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
def hashed_label(boolean = nil)
|
40
|
-
if !boolean.nil?
|
41
|
-
options[:hashed_label] = boolean
|
42
|
-
else
|
43
|
-
options[:hashed_label] || nil
|
44
|
-
end
|
45
|
-
end
|
37
|
+
option_accessor :depth
|
38
|
+
option_accessor :class_name
|
39
|
+
option_accessor :store_event
|
40
|
+
option_accessor :hashed_label
|
41
|
+
option_accessor :label_indexing
|
46
42
|
|
47
|
-
def class_name(class_name = nil)
|
48
|
-
if !class_name.nil?
|
49
|
-
options[:class_name] = class_name
|
50
|
-
else
|
51
|
-
options[:class_name] || nil
|
52
|
-
end
|
53
|
-
end
|
54
43
|
alias :scope :class_name
|
55
44
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
else
|
60
|
-
options[:depth] || nil
|
61
|
-
end
|
45
|
+
def connect_to(opts = {})
|
46
|
+
Connection.create(opts.merge(:ref => name))
|
47
|
+
options[:connection_ref] = name
|
62
48
|
end
|
63
49
|
|
64
|
-
def store_event(boolean = nil)
|
65
|
-
if !boolean.nil?
|
66
|
-
options[:store_event] = boolean
|
67
|
-
else
|
68
|
-
options[:store_event] || nil
|
69
|
-
end
|
70
|
-
end
|
71
50
|
|
72
51
|
#
|
73
52
|
# resource access methods
|
@@ -78,10 +57,6 @@ module Redistat
|
|
78
57
|
end
|
79
58
|
alias :redis :connection
|
80
59
|
|
81
|
-
def options
|
82
|
-
@options ||= {}
|
83
|
-
end
|
84
|
-
|
85
60
|
def name
|
86
61
|
options[:class_name] || (@name ||= self.to_s)
|
87
62
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Redistat
|
2
|
+
module Options
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
class InvalidDefaultOptions < ArgumentError; end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def option_accessor(*opts)
|
12
|
+
opts.each do |option|
|
13
|
+
define_method(option) do |*args|
|
14
|
+
if !args.first.nil?
|
15
|
+
options[option.to_sym] = args.first
|
16
|
+
else
|
17
|
+
options[option.to_sym] || nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse_options(opts)
|
25
|
+
opts ||= {}
|
26
|
+
@raw_options = opts
|
27
|
+
@options = default_options.merge(opts.reject { |k,v| v.nil? })
|
28
|
+
end
|
29
|
+
|
30
|
+
def default_options
|
31
|
+
{}
|
32
|
+
end
|
33
|
+
|
34
|
+
def options
|
35
|
+
@options ||= {}
|
36
|
+
end
|
37
|
+
|
38
|
+
def raw_options
|
39
|
+
@raw_options ||= {}
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
data/lib/redistat/summary.rb
CHANGED
@@ -2,20 +2,28 @@ module Redistat
|
|
2
2
|
class Summary
|
3
3
|
include Database
|
4
4
|
|
5
|
-
def self.
|
5
|
+
def self.default_options
|
6
|
+
{ :enable_grouping => true,
|
7
|
+
:label_indexing => true,
|
8
|
+
:connection_ref => nil }
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.update_all(key, stats = {}, depth_limit = nil, opts = {})
|
6
12
|
stats ||= {}
|
7
13
|
return nil if stats.size == 0
|
8
14
|
|
15
|
+
options = default_options.merge((opts || {}).reject { |k,v| v.nil? })
|
16
|
+
|
9
17
|
depth_limit ||= key.depth
|
10
|
-
enable_grouping = true if enable_grouping.nil?
|
11
18
|
|
12
|
-
if enable_grouping
|
19
|
+
if options[:enable_grouping]
|
13
20
|
stats = inject_group_summaries(stats)
|
14
21
|
key.groups.each { |k|
|
15
|
-
update_key(k, stats, depth_limit, connection_ref)
|
22
|
+
update_key(k, stats, depth_limit, options[:connection_ref])
|
23
|
+
k.update_index if options[:label_indexing]
|
16
24
|
}
|
17
25
|
else
|
18
|
-
update_key(key, stats, depth_limit, connection_ref)
|
26
|
+
update_key(key, stats, depth_limit, options[:connection_ref])
|
19
27
|
end
|
20
28
|
end
|
21
29
|
|
data/lib/redistat/version.rb
CHANGED
data/redistat.gemspec
CHANGED
data/spec/event_spec.rb
CHANGED
@@ -18,7 +18,7 @@ describe Redistat::Event do
|
|
18
18
|
it "should initialize properly" do
|
19
19
|
@event.id.should be_nil
|
20
20
|
@event.scope.should == @scope
|
21
|
-
@event.label.should == @label
|
21
|
+
@event.label.to_s.should == @label
|
22
22
|
@event.label_hash.should == @label_hash
|
23
23
|
@event.date.to_time.to_s.should == @date.to_s
|
24
24
|
@event.stats.should == @stats
|
@@ -33,12 +33,12 @@ describe Redistat::Event do
|
|
33
33
|
@event.date = @date
|
34
34
|
@event.date.to_time.to_s.should == @date.to_s
|
35
35
|
# label
|
36
|
-
@event.label.should == @label
|
36
|
+
@event.label.to_s.should == @label
|
37
37
|
@event.label_hash.should == @label_hash
|
38
38
|
@label = "contact_us"
|
39
39
|
@label_hash = Digest::SHA1.hexdigest(@label)
|
40
40
|
@event.label = @label
|
41
|
-
@event.label.should == @label
|
41
|
+
@event.label.to_s.should == @label
|
42
42
|
@event.label_hash.should == @label_hash
|
43
43
|
end
|
44
44
|
|
@@ -64,7 +64,7 @@ describe Redistat::Event do
|
|
64
64
|
@event = Redistat::Event.new(@scope, @label, @date, @stats, @options.merge({:store_event => true}), @meta).save
|
65
65
|
fetched = Redistat::Event.find(@scope, @event.id)
|
66
66
|
@event.scope.should == fetched.scope
|
67
|
-
@event.label.should == fetched.label
|
67
|
+
@event.label.to_s.should == fetched.label.to_s
|
68
68
|
@event.date.to_s.should == fetched.date.to_s
|
69
69
|
end
|
70
70
|
|
data/spec/finder_spec.rb
CHANGED
@@ -9,41 +9,43 @@ describe Redistat::Finder do
|
|
9
9
|
@label = "about_us"
|
10
10
|
@date = Time.now
|
11
11
|
@key = Redistat::Key.new(@scope, @label, @date, {:depth => :day})
|
12
|
-
@stats = {"views" => 3, "visitors" => 2}
|
12
|
+
@stats = {"views" => 3, "visitors" => 2}
|
13
|
+
@two_hours_ago = 2.hours.ago
|
14
|
+
@one_hour_ago = 1.hour.ago
|
13
15
|
end
|
14
16
|
|
15
17
|
it "should initialize properly" do
|
16
|
-
|
17
|
-
one_hour_ago = 1.hour.ago
|
18
|
-
options = {:scope => "PageViews", :label => "Label", :from => two_hours_ago, :till => one_hour_ago, :depth => :hour, :interval => :hour}
|
19
|
-
|
20
|
-
finder = Redistat::Finder.new(options)
|
21
|
-
finder.options.should == options
|
18
|
+
options = {:scope => "PageViews", :label => "Label", :from => @two_hours_ago, :till => @one_hour_ago, :depth => :hour, :interval => :hour}
|
22
19
|
|
23
20
|
finder = Redistat::Finder.new
|
24
21
|
finder.send(:set_options, options)
|
25
|
-
finder.options.should
|
26
|
-
|
27
|
-
finder
|
28
|
-
finder.options.should == options
|
29
|
-
|
30
|
-
|
31
|
-
finder.
|
22
|
+
finder.options[:scope].should be_a(Redistat::Scope)
|
23
|
+
finder.options[:scope].to_s.should == options[:scope]
|
24
|
+
finder.options[:label].should be_a(Redistat::Label)
|
25
|
+
finder.options[:label].to_s.should == options[:label]
|
26
|
+
finder.options.should == options.merge(:scope => finder.options[:scope], :label => finder.options[:label])
|
27
|
+
|
28
|
+
finder = Redistat::Finder.dates(@two_hours_ago, @one_hour_ago)
|
29
|
+
finder.options[:from].should == @two_hours_ago
|
30
|
+
finder.options[:till].should == @one_hour_ago
|
31
|
+
|
32
|
+
finder = Redistat::Finder.scope("hello")
|
33
|
+
finder.options[:scope].to_s.should == "hello"
|
32
34
|
|
33
|
-
finder = Redistat::Finder.label("
|
34
|
-
finder.options.should ==
|
35
|
+
finder = Redistat::Finder.label("hello")
|
36
|
+
finder.options[:label].to_s.should == "hello"
|
35
37
|
|
36
|
-
finder = Redistat::Finder.from(two_hours_ago)
|
37
|
-
finder.options.should ==
|
38
|
+
finder = Redistat::Finder.from(@two_hours_ago)
|
39
|
+
finder.options[:from].should == @two_hours_ago
|
38
40
|
|
39
|
-
finder = Redistat::Finder.till(one_hour_ago)
|
40
|
-
finder.options.should ==
|
41
|
+
finder = Redistat::Finder.till(@one_hour_ago)
|
42
|
+
finder.options[:till].should == @one_hour_ago
|
41
43
|
|
42
|
-
finder = Redistat::Finder.depth(:hour)
|
43
|
-
finder.options.should ==
|
44
|
+
finder = Redistat::Finder.depth(:hour)
|
45
|
+
finder.options[:depth].should == :hour
|
44
46
|
|
45
|
-
finder = Redistat::Finder.interval(:hour)
|
46
|
-
finder.options.should ==
|
47
|
+
finder = Redistat::Finder.interval(:hour)
|
48
|
+
finder.options[:interval].should == :hour
|
47
49
|
|
48
50
|
end
|
49
51
|
|
@@ -89,6 +91,21 @@ describe Redistat::Finder do
|
|
89
91
|
lambda { Redistat::Finder.find(:from => 3.hours.ago) }.should raise_error(Redistat::InvalidOptions)
|
90
92
|
end
|
91
93
|
|
94
|
+
it "should find children" do
|
95
|
+
Redistat::Key.new("PageViews", "message/public/die").update_index
|
96
|
+
Redistat::Key.new("PageViews", "message/public/live").update_index
|
97
|
+
Redistat::Key.new("PageViews", "message/public/fester").update_index
|
98
|
+
members = db.smembers("#{@scope}#{Redistat::LABEL_INDEX}message/public") # checking 'message/public'
|
99
|
+
options = {:scope => "PageViews", :label => "message/public", :from => @two_hours_ago, :till => @one_hour_ago, :depth => :hour, :interval => :hour}
|
100
|
+
finder = Redistat::Finder.new(options)
|
101
|
+
finder.children.first.should be_a(Redistat::Finder)
|
102
|
+
subs = finder.children.map { |f| f.options[:label].me }
|
103
|
+
subs.should have(3).items
|
104
|
+
subs.should include('die')
|
105
|
+
subs.should include('live')
|
106
|
+
subs.should include('fester')
|
107
|
+
end
|
108
|
+
|
92
109
|
describe "Lazy-Loading" do
|
93
110
|
|
94
111
|
before(:each) do
|
@@ -103,7 +120,6 @@ describe Redistat::Finder do
|
|
103
120
|
end
|
104
121
|
|
105
122
|
it "should lazy-load" do
|
106
|
-
|
107
123
|
@finder.instance_variable_get("@result").should be_nil
|
108
124
|
stats = @finder.all
|
109
125
|
@finder.instance_variable_get("@result").should_not be_nil
|
@@ -146,7 +162,7 @@ describe Redistat::Finder do
|
|
146
162
|
res.should == match
|
147
163
|
end
|
148
164
|
|
149
|
-
end
|
165
|
+
end # "Lazy-Loading"
|
150
166
|
|
151
167
|
|
152
168
|
# helper methods
|
data/spec/key_spec.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Redistat::Key do
|
4
|
+
include Redistat::Database
|
4
5
|
|
5
6
|
before(:each) do
|
7
|
+
db.flushdb
|
6
8
|
@scope = "PageViews"
|
7
9
|
@label = "about_us"
|
8
10
|
@label_hash = Digest::SHA1.hexdigest(@label)
|
@@ -12,9 +14,9 @@ describe Redistat::Key do
|
|
12
14
|
|
13
15
|
it "should initialize properly" do
|
14
16
|
@key.scope.should == @scope
|
15
|
-
@key.label.should == @label
|
17
|
+
@key.label.to_s.should == @label
|
16
18
|
@key.label_hash.should == @label_hash
|
17
|
-
@key.
|
19
|
+
@key.groups.map { |k| k.instance_variable_get("@label") }.should == @key.instance_variable_get("@label").groups
|
18
20
|
@key.date.should be_instance_of(Redistat::Date)
|
19
21
|
@key.date.to_time.to_s.should == @date.to_s
|
20
22
|
end
|
@@ -52,25 +54,74 @@ describe Redistat::Key do
|
|
52
54
|
@key.date = @date
|
53
55
|
@key.date.to_time.to_s.should == @date.to_s
|
54
56
|
# label
|
55
|
-
@key.label.should == @label
|
57
|
+
@key.label.to_s.should == @label
|
56
58
|
@key.label_hash == @label_hash
|
57
59
|
@label = "contact_us"
|
58
60
|
@label_hash = Digest::SHA1.hexdigest(@label)
|
59
61
|
@key.label = @label
|
60
|
-
@key.label.should == @label
|
62
|
+
@key.label.to_s.should == @label
|
61
63
|
@key.label_hash == @label_hash
|
62
64
|
end
|
63
65
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
describe "Grouping" do
|
67
|
+
before(:each) do
|
68
|
+
@label = "message/public/offensive"
|
69
|
+
@key = Redistat::Key.new(@scope, @label, @date, {:depth => :hour})
|
70
|
+
end
|
69
71
|
|
70
|
-
|
72
|
+
it "should create a group of keys from label group" do
|
73
|
+
label = 'message/public/offensive'
|
74
|
+
result = [ "message/public/offensive",
|
75
|
+
"message/public",
|
76
|
+
"message" ]
|
77
|
+
|
78
|
+
key = Redistat::Key.new(@scope, label, @date, {:depth => :hour})
|
79
|
+
|
80
|
+
key.groups.map { |k| k.label.to_s }.should == result
|
81
|
+
end
|
71
82
|
|
72
|
-
|
73
|
-
|
83
|
+
it "should know it's parent" do
|
84
|
+
@key.parent.should be_a(Redistat::Key)
|
85
|
+
@key.parent.label.to_s.should == 'message/public'
|
86
|
+
Redistat::Key.new(@scope, 'hello', @date).parent.should be_nil
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should update label index and return children" do
|
90
|
+
db.smembers("#{@scope}#{Redistat::LABEL_INDEX}#{@key.label.parent}").should == []
|
91
|
+
@key.children.should have(0).items
|
92
|
+
|
93
|
+
@key.update_index # indexing 'message/publish/offensive'
|
94
|
+
Redistat::Key.new("PageViews", "message/public/die").update_index # indexing 'message/publish/die'
|
95
|
+
Redistat::Key.new("PageViews", "message/public/live").update_index # indexing 'message/publish/live'
|
96
|
+
|
97
|
+
members = db.smembers("#{@scope}#{Redistat::LABEL_INDEX}#{@key.label.parent}") # checking 'message/public'
|
98
|
+
members.should have(3).item
|
99
|
+
members.should include('offensive')
|
100
|
+
members.should include('live')
|
101
|
+
members.should include('die')
|
102
|
+
|
103
|
+
key = @key.parent
|
104
|
+
key.children.first.should be_a(Redistat::Key)
|
105
|
+
key.children.should have(3).item
|
106
|
+
key.children.map { |k| k.label.me }.should == members
|
107
|
+
|
108
|
+
members = db.smembers("#{@scope}#{Redistat::LABEL_INDEX}#{key.label.parent}") # checking 'message'
|
109
|
+
members.should have(1).item
|
110
|
+
members.should include('public')
|
111
|
+
|
112
|
+
key = key.parent
|
113
|
+
key.children.should have(1).item
|
114
|
+
key.children.map { |k| k.label.me }.should == members
|
115
|
+
|
116
|
+
members = db.smembers("#{@scope}#{Redistat::LABEL_INDEX}") # checking ''
|
117
|
+
members.should have(1).item
|
118
|
+
members.should include('message')
|
119
|
+
|
120
|
+
key.parent.should be_nil
|
121
|
+
key = Redistat::Key.new("PageViews")
|
122
|
+
key.children.should have(1).item
|
123
|
+
key.children.map { |k| k.label.me }.should include('message')
|
124
|
+
end
|
74
125
|
end
|
75
126
|
|
76
127
|
end
|
data/spec/label_spec.rb
CHANGED
@@ -17,32 +17,42 @@ describe Redistat::Label do
|
|
17
17
|
it "should store a label hash lookup key" do
|
18
18
|
label = Redistat::Label.new(@name, {:hashed_label => true}).save
|
19
19
|
label.saved?.should be_true
|
20
|
-
db.
|
20
|
+
db.hget(Redistat::KEY_LEBELS, label.hash).should == @name
|
21
21
|
|
22
22
|
name = "contact_us"
|
23
23
|
label = Redistat::Label.create(name, {:hashed_label => true})
|
24
24
|
label.saved?.should be_true
|
25
|
-
db.
|
25
|
+
db.hget(Redistat::KEY_LEBELS, label.hash).should == name
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
describe "Grouping" do
|
29
|
+
before(:each) do
|
30
|
+
@name = "message/public/offensive"
|
31
|
+
@label = Redistat::Label.new(@name)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should know it's parent label group" do
|
35
|
+
@label.parent.to_s.should == 'message/public'
|
36
|
+
Redistat::Label.new('hello').parent.should be_nil
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should separate label names into groups" do
|
40
|
+
@label.name.should == @name
|
41
|
+
@label.groups.map { |l| l.to_s }.should == [ "message/public/offensive",
|
42
|
+
"message/public",
|
43
|
+
"message" ]
|
35
44
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
45
|
+
@name = "/message/public/"
|
46
|
+
@label = Redistat::Label.new(@name)
|
47
|
+
@label.name.should == @name
|
48
|
+
@label.groups.map { |l| l.to_s }.should == [ "message/public",
|
49
|
+
"message" ]
|
41
50
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
51
|
+
@name = "message"
|
52
|
+
@label = Redistat::Label.new(@name)
|
53
|
+
@label.name.should == @name
|
54
|
+
@label.groups.map { |l| l.to_s }.should == [ "message" ]
|
55
|
+
end
|
46
56
|
end
|
47
57
|
|
48
58
|
end
|
data/spec/model_spec.rb
CHANGED
@@ -22,8 +22,8 @@ describe Redistat::Model do
|
|
22
22
|
one_hour_ago = 1.hour.ago
|
23
23
|
finder = ModelHelper1.find('label', two_hours_ago, one_hour_ago)
|
24
24
|
finder.should be_a(Redistat::Finder)
|
25
|
-
finder.options[:scope].should == 'ModelHelper1'
|
26
|
-
finder.options[:label].should == 'label'
|
25
|
+
finder.options[:scope].to_s.should == 'ModelHelper1'
|
26
|
+
finder.options[:label].to_s.should == 'label'
|
27
27
|
finder.options[:from].should == two_hours_ago
|
28
28
|
finder.options[:till].should == one_hour_ago
|
29
29
|
end
|
@@ -82,34 +82,71 @@ describe Redistat::Model do
|
|
82
82
|
stats.first.should == stats.total
|
83
83
|
end
|
84
84
|
|
85
|
+
it "should store and fetch grouping enabled stats" do
|
86
|
+
ModelHelper1.store("sheep/black", {:count => 6, :weight => 461}, @time.hours_ago(4))
|
87
|
+
ModelHelper1.store("sheep/black", {:count => 2, :weight => 156}, @time)
|
88
|
+
ModelHelper1.store("sheep/white", {:count => 5, :weight => 393}, @time.hours_ago(4))
|
89
|
+
ModelHelper1.store("sheep/white", {:count => 4, :weight => 316}, @time)
|
90
|
+
|
91
|
+
stats = ModelHelper1.fetch("sheep/black", @time.hours_ago(2), @time.hours_since(1))
|
92
|
+
stats.total["count"].should == 2
|
93
|
+
stats.total["weight"].should == 156
|
94
|
+
stats.first.should == stats.total
|
95
|
+
|
96
|
+
stats = ModelHelper1.fetch("sheep/black", @time.hours_ago(5), @time.hours_since(1))
|
97
|
+
stats.total[:count].should == 8
|
98
|
+
stats.total[:weight].should == 617
|
99
|
+
stats.first.should == stats.total
|
100
|
+
|
101
|
+
stats = ModelHelper1.fetch("sheep/white", @time.hours_ago(2), @time.hours_since(1))
|
102
|
+
stats.total[:count].should == 4
|
103
|
+
stats.total[:weight].should == 316
|
104
|
+
stats.first.should == stats.total
|
105
|
+
|
106
|
+
stats = ModelHelper1.fetch("sheep/white", @time.hours_ago(5), @time.hours_since(1))
|
107
|
+
stats.total[:count].should == 9
|
108
|
+
stats.total[:weight].should == 709
|
109
|
+
stats.first.should == stats.total
|
110
|
+
|
111
|
+
stats = ModelHelper1.fetch("sheep", @time.hours_ago(2), @time.hours_since(1))
|
112
|
+
stats.total[:count].should == 6
|
113
|
+
stats.total[:weight].should == 472
|
114
|
+
stats.first.should == stats.total
|
115
|
+
|
116
|
+
stats = ModelHelper1.fetch("sheep", @time.hours_ago(5), @time.hours_since(1))
|
117
|
+
stats.total[:count].should == 17
|
118
|
+
stats.total[:weight].should == 1326
|
119
|
+
stats.first.should == stats.total
|
120
|
+
end
|
121
|
+
|
85
122
|
it "should connect to different Redis servers on a per-model basis" do
|
86
123
|
ModelHelper3.redis.client.db.should == 14
|
87
124
|
|
88
|
-
ModelHelper3.store("sheep.black", {:count => 6, :weight => 461}, @time.hours_ago(4))
|
89
|
-
ModelHelper3.store("sheep.black", {:count => 2, :weight => 156}, @time)
|
125
|
+
ModelHelper3.store("sheep.black", {:count => 6, :weight => 461}, @time.hours_ago(4), :label_indexing => false)
|
126
|
+
ModelHelper3.store("sheep.black", {:count => 2, :weight => 156}, @time, :label_indexing => false)
|
90
127
|
|
91
128
|
db.keys("*").should be_empty
|
92
129
|
ModelHelper1.redis.keys("*").should be_empty
|
93
130
|
db("ModelHelper3").keys("*").should have(5).items
|
94
131
|
ModelHelper3.redis.keys("*").should have(5).items
|
95
132
|
|
96
|
-
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(2), @time.hours_since(1))
|
133
|
+
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(2), @time.hours_since(1), :label_indexing => false)
|
97
134
|
stats.total["count"].should == 2
|
98
135
|
stats.total["weight"].should == 156
|
99
|
-
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1))
|
136
|
+
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1), :label_indexing => false)
|
100
137
|
stats.total[:count].should == 8
|
101
138
|
stats.total[:weight].should == 617
|
102
139
|
|
103
140
|
ModelHelper3.connect_to(:port => 8379, :db => 13)
|
104
141
|
ModelHelper3.redis.client.db.should == 13
|
105
142
|
|
106
|
-
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1))
|
143
|
+
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1), :label_indexing => false)
|
107
144
|
stats.total.should == {}
|
108
145
|
|
109
146
|
ModelHelper3.connect_to(:port => 8379, :db => 14)
|
110
147
|
ModelHelper3.redis.client.db.should == 14
|
111
148
|
|
112
|
-
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1))
|
149
|
+
stats = ModelHelper3.fetch("sheep.black", @time.hours_ago(5), @time.hours_since(1), :label_indexing => false)
|
113
150
|
stats.total[:count].should == 8
|
114
151
|
stats.total[:weight].should == 617
|
115
152
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Redistat::Options do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@helper = OptionsHelper.new
|
7
|
+
@helper.parse_options(:wtf => 'dude', :foo => 'booze')
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should #parse_options" do
|
11
|
+
@helper.options[:hello].should == 'world'
|
12
|
+
@helper.options[:foo].should == 'booze'
|
13
|
+
@helper.options[:wtf].should == 'dude'
|
14
|
+
@helper.raw_options.should_not have_key(:hello)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should create option_accessors" do
|
18
|
+
@helper.hello.should == 'world'
|
19
|
+
@helper.hello('woooo')
|
20
|
+
@helper.hello.should == 'woooo'
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class OptionsHelper
|
26
|
+
include Redistat::Options
|
27
|
+
|
28
|
+
option_accessor :hello
|
29
|
+
|
30
|
+
def default_options
|
31
|
+
{ :hello => 'world',
|
32
|
+
:foo => 'bar' }
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
end
|
data/spec/summary_spec.rb
CHANGED
@@ -69,7 +69,7 @@ describe Redistat::Summary do
|
|
69
69
|
|
70
70
|
it "should not store key group summaries when option is disabled" do
|
71
71
|
stats = {"views" => 3, "visitors/eu" => 2, "visitors/us" => 4}
|
72
|
-
Redistat::Summary.update_all(@key, stats, :hour,
|
72
|
+
Redistat::Summary.update_all(@key, stats, :hour, {:enable_grouping => false})
|
73
73
|
summary = db.hgetall(@key.to_s(:hour))
|
74
74
|
summary.should have(3).items
|
75
75
|
summary["views"].should == "3"
|
@@ -83,8 +83,8 @@ describe Redistat::Summary do
|
|
83
83
|
key = Redistat::Key.new(@scope, label, @date)
|
84
84
|
Redistat::Summary.update_all(key, stats, :hour)
|
85
85
|
|
86
|
-
key.groups[0].label.should == "views/about_us"
|
87
|
-
key.groups[1].label.should == "views"
|
86
|
+
key.groups[0].label.to_s.should == "views/about_us"
|
87
|
+
key.groups[1].label.to_s.should == "views"
|
88
88
|
child1 = key.groups[0]
|
89
89
|
parent = key.groups[1]
|
90
90
|
|
@@ -92,8 +92,8 @@ describe Redistat::Summary do
|
|
92
92
|
key = Redistat::Key.new(@scope, label, @date)
|
93
93
|
Redistat::Summary.update_all(key, stats, :hour)
|
94
94
|
|
95
|
-
key.groups[0].label.should == "views/contact"
|
96
|
-
key.groups[1].label.should == "views"
|
95
|
+
key.groups[0].label.to_s.should == "views/contact"
|
96
|
+
key.groups[1].label.to_s.should == "views"
|
97
97
|
child2 = key.groups[0]
|
98
98
|
|
99
99
|
summary = db.hgetall(child1.to_s(:hour))
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redistat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jim Myhrberg
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-03-
|
18
|
+
date: 2011-03-10 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -130,6 +130,20 @@ dependencies:
|
|
130
130
|
version: 0.6.3
|
131
131
|
type: :development
|
132
132
|
version_requirements: *id007
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: ruby-debug
|
135
|
+
prerelease: false
|
136
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
hash: 3
|
142
|
+
segments:
|
143
|
+
- 0
|
144
|
+
version: "0"
|
145
|
+
type: :development
|
146
|
+
version_requirements: *id008
|
133
147
|
description: A Redis-backed statistics storage and querying library written in Ruby.
|
134
148
|
email:
|
135
149
|
- contact@jimeh.me
|
@@ -164,6 +178,7 @@ files:
|
|
164
178
|
- lib/redistat/key.rb
|
165
179
|
- lib/redistat/label.rb
|
166
180
|
- lib/redistat/model.rb
|
181
|
+
- lib/redistat/options.rb
|
167
182
|
- lib/redistat/result.rb
|
168
183
|
- lib/redistat/scope.rb
|
169
184
|
- lib/redistat/summary.rb
|
@@ -181,6 +196,7 @@ files:
|
|
181
196
|
- spec/label_spec.rb
|
182
197
|
- spec/model_helper.rb
|
183
198
|
- spec/model_spec.rb
|
199
|
+
- spec/options_spec.rb
|
184
200
|
- spec/redis-test.conf
|
185
201
|
- spec/result_spec.rb
|
186
202
|
- spec/scope_spec.rb
|
@@ -234,6 +250,7 @@ test_files:
|
|
234
250
|
- spec/label_spec.rb
|
235
251
|
- spec/model_helper.rb
|
236
252
|
- spec/model_spec.rb
|
253
|
+
- spec/options_spec.rb
|
237
254
|
- spec/redis-test.conf
|
238
255
|
- spec/result_spec.rb
|
239
256
|
- spec/scope_spec.rb
|