trackoid 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +14 -0
- data/VERSION +1 -1
- data/lib/trackoid/tracker.rb +51 -7
- data/spec/trackoid_spec.rb +76 -13
- data/trackoid.gemspec +2 -2
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -183,3 +183,17 @@ MongoDB stores information in BSON format as a binary representation of a JSON s
|
|
183
183
|
A year full of statistical data takes only 2.8Kb, if you store integers. If your statistical data includes floats, a year full of information takes 4.3Kb. I said "a year full of data" because Trackoid does not store information for days without data.
|
184
184
|
|
185
185
|
For comparison, this README is already 8.5Kb in size.
|
186
|
+
|
187
|
+
|
188
|
+
= Revision History
|
189
|
+
|
190
|
+
0.1.6 - Enabled support for String dates in operators. This string date must
|
191
|
+
be DateTime parseable.
|
192
|
+
For example: @spain.world_cups.inc("2010-07-11")
|
193
|
+
- Normalized Date and DateTime objects to use only Date methods.
|
194
|
+
- Added "first" / "first_date" / "last" / "last_date" accessors.
|
195
|
+
- Added "all" accessor.
|
196
|
+
|
197
|
+
0.1.5 - Added support for namespaced models and aggregations
|
198
|
+
- Enabled "set" operations on aggregates
|
199
|
+
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.6
|
data/lib/trackoid/tracker.rb
CHANGED
@@ -32,8 +32,8 @@ module Mongoid #:nodoc:
|
|
32
32
|
end
|
33
33
|
|
34
34
|
# Update methods
|
35
|
-
def add(how_much = 1, date =
|
36
|
-
raise Errors::ModelNotSaved, "Can't update a new record" if @owner.new_record?
|
35
|
+
def add(how_much = 1, date = Date.today)
|
36
|
+
raise Errors::ModelNotSaved, "Can't update a new record. Save first!" if @owner.new_record?
|
37
37
|
update_data(data_for(date) + how_much, date)
|
38
38
|
@owner.collection.update( @owner._selector,
|
39
39
|
{ (how_much > 0 ? "$inc" : "$dec") => update_hash(how_much.abs, date) },
|
@@ -50,15 +50,15 @@ module Mongoid #:nodoc:
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
def inc(date =
|
53
|
+
def inc(date = Date.today)
|
54
54
|
add(1, date)
|
55
55
|
end
|
56
56
|
|
57
|
-
def dec(date =
|
57
|
+
def dec(date = Date.today)
|
58
58
|
add(-1, date)
|
59
59
|
end
|
60
60
|
|
61
|
-
def set(how_much, date =
|
61
|
+
def set(how_much, date = Date.today)
|
62
62
|
raise Errors::ModelNotSaved, "Can't update a new record" if @owner.new_record?
|
63
63
|
update_data(how_much, date)
|
64
64
|
@owner.collection.update( @owner._selector,
|
@@ -78,6 +78,14 @@ module Mongoid #:nodoc:
|
|
78
78
|
|
79
79
|
|
80
80
|
# Access methods
|
81
|
+
def first
|
82
|
+
data_for(first_date)
|
83
|
+
end
|
84
|
+
|
85
|
+
def last
|
86
|
+
data_for(last_date)
|
87
|
+
end
|
88
|
+
|
81
89
|
def today
|
82
90
|
data_for(Date.today)
|
83
91
|
end
|
@@ -88,24 +96,50 @@ module Mongoid #:nodoc:
|
|
88
96
|
|
89
97
|
def last_days(how_much = 7)
|
90
98
|
return [today] unless how_much > 0
|
91
|
-
date, values =
|
99
|
+
date, values = Date.today, []
|
92
100
|
(date - how_much.abs + 1).step(date) {|d| values << data_for(d) }
|
93
101
|
values
|
94
102
|
end
|
95
103
|
|
96
104
|
def on(date)
|
97
|
-
date = DateTime.parse(date) if date.is_a?(String)
|
98
105
|
return date.collect {|d| data_for(d)} if date.is_a?(Range)
|
99
106
|
data_for(date)
|
100
107
|
end
|
101
108
|
|
109
|
+
def all
|
110
|
+
on(first_date..last_date) if first_date
|
111
|
+
end
|
112
|
+
|
113
|
+
# Utility methods
|
114
|
+
def first_date
|
115
|
+
# We are guaranteed _m and _d to exists unless @data is a malformed
|
116
|
+
# hash, so we need to do this nasty "return nil", sorry...
|
117
|
+
return nil unless _y = @data.keys.min
|
118
|
+
return nil unless _m = @data[_y].keys.min
|
119
|
+
return nil unless _d = @data[_y][_m].keys.min
|
120
|
+
Date.new(_y.to_i, _m.to_i, _d.to_i)
|
121
|
+
end
|
122
|
+
|
123
|
+
def last_date
|
124
|
+
# We are guaranteed _m and _d to exists unless @data is a malformed
|
125
|
+
# hash, so we need to do this nasty "return nil", sorry...
|
126
|
+
return nil unless _y = @data.keys.max
|
127
|
+
return nil unless _m = @data[_y].keys.max
|
128
|
+
return nil unless _d = @data[_y][_m].keys.max
|
129
|
+
Date.new(_y.to_i, _m.to_i, _d.to_i)
|
130
|
+
end
|
131
|
+
|
102
132
|
# Private methods
|
103
133
|
private
|
104
134
|
def data_for(date)
|
135
|
+
return nil if date.nil?
|
136
|
+
date = normalize_date(date)
|
105
137
|
@data.try(:[], date.year.to_s).try(:[], date.month.to_s).try(:[], date.day.to_s) || 0
|
106
138
|
end
|
107
139
|
|
108
140
|
def update_data(value, date)
|
141
|
+
return nil if date.nil?
|
142
|
+
date = normalize_date(date)
|
109
143
|
[:year, :month].inject(@data) { |data, period|
|
110
144
|
data[date.send(period).to_s] ||= {}
|
111
145
|
}
|
@@ -117,11 +151,21 @@ module Mongoid #:nodoc:
|
|
117
151
|
def date_literal(d); "#{d.year}.#{d.month}.#{d.day}"; end
|
118
152
|
|
119
153
|
def update_hash(num, date)
|
154
|
+
date = normalize_date(date)
|
120
155
|
{
|
121
156
|
"#{@for_data}.#{date_literal(date)}" => num
|
122
157
|
}
|
123
158
|
end
|
124
159
|
|
160
|
+
def normalize_date(date)
|
161
|
+
case date
|
162
|
+
when String
|
163
|
+
Date.parse(date)
|
164
|
+
else
|
165
|
+
date
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
125
169
|
# WARNING: This is +only+ for debugging pourposes (rspec y tal)
|
126
170
|
def _original_hash
|
127
171
|
@data
|
data/spec/trackoid_spec.rb
CHANGED
@@ -9,7 +9,6 @@ class Test
|
|
9
9
|
end
|
10
10
|
|
11
11
|
describe Mongoid::Tracking do
|
12
|
-
|
13
12
|
before(:all) do
|
14
13
|
@trackoid_version = File.read(File.expand_path("../VERSION", File.dirname(__FILE__)))
|
15
14
|
end
|
@@ -38,7 +37,6 @@ describe Mongoid::Tracking do
|
|
38
37
|
end
|
39
38
|
|
40
39
|
describe "when creating a new field with stats" do
|
41
|
-
|
42
40
|
before(:all) do
|
43
41
|
@mock = Test.new
|
44
42
|
end
|
@@ -96,11 +94,9 @@ describe Mongoid::Tracking do
|
|
96
94
|
it "should not be aggregated" do
|
97
95
|
@mock.aggregated?.should be_false
|
98
96
|
end
|
99
|
-
|
100
97
|
end
|
101
98
|
|
102
99
|
describe "when using a model in the database" do
|
103
|
-
|
104
100
|
before(:all) do
|
105
101
|
Test.delete_all
|
106
102
|
Test.create(:name => "test")
|
@@ -143,10 +139,84 @@ describe Mongoid::Tracking do
|
|
143
139
|
@mock.visits.last_days.should == [0, 0, 0, 0, 0, 2, 2]
|
144
140
|
end
|
145
141
|
|
142
|
+
it "string dates should work" do
|
143
|
+
@mock.visits.inc("2010-07-11")
|
144
|
+
@mock.visits.on("2010-07-11").should == 1
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should give the first date with first_date" do
|
148
|
+
@mock.visits.first_date.should == Date.parse("2010-07-11")
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should give the last date with last_date" do
|
152
|
+
@mock.visits.last_date.should == Date.today
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should give the first value" do
|
156
|
+
@mock.visits.first.should == 1
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should give the last value" do
|
160
|
+
@mock.visits.last.should == 2
|
161
|
+
end
|
146
162
|
end
|
147
163
|
|
148
|
-
|
164
|
+
describe "Testing accessors with an empty model" do
|
165
|
+
before do
|
166
|
+
Test.delete_all
|
167
|
+
Test.create(:name => "test")
|
168
|
+
@object_id = Test.first.id
|
169
|
+
@mock = Test.first
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should return nil for .first_date" do
|
173
|
+
@mock.visits.first_date.should be_nil
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should return nil for .last_date" do
|
177
|
+
@mock.visits.last_date.should be_nil
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should return nil for .first" do
|
181
|
+
@mock.visits.first.should be_nil
|
182
|
+
end
|
149
183
|
|
184
|
+
it "should return nil for .last" do
|
185
|
+
@mock.visits.last.should be_nil
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should return nil for .all" do
|
189
|
+
@mock.visits.all.should be_nil
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "Testing new range accessors with an empty model" do
|
194
|
+
before do
|
195
|
+
Test.delete_all
|
196
|
+
Test.create(:name => "test")
|
197
|
+
@object_id = Test.first.id
|
198
|
+
@mock = Test.first
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should return the correct values for .all" do
|
202
|
+
@mock.visits.set(1, "2010-07-11")
|
203
|
+
@mock.visits.set(2, "2010-07-12")
|
204
|
+
@mock.visits.set(3, "2010-07-13")
|
205
|
+
|
206
|
+
@mock.visits.all.should == [1, 2, 3]
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should return the correct values for .all (Take II)" do
|
210
|
+
@mock.visits.set(5, "2010-07-01")
|
211
|
+
@mock.visits.set(10, "2010-07-30")
|
212
|
+
|
213
|
+
@mock.visits.all.should == [5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10]
|
214
|
+
@mock.visits.last.should == 10
|
215
|
+
@mock.visits.first.should == 5
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context "testing accessor operations without reloading models" do
|
150
220
|
before(:all) do
|
151
221
|
Test.delete_all
|
152
222
|
Test.create(:name => "test")
|
@@ -195,15 +265,10 @@ describe Mongoid::Tracking do
|
|
195
265
|
# We have data for today as previous tests populated the visits field
|
196
266
|
@mock.visits.on(Date.parse("2010-04-30")..Date.parse("2010-05-02")).should == [0, 10, 0]
|
197
267
|
end
|
198
|
-
|
199
|
-
|
200
268
|
end
|
201
269
|
|
202
|
-
|
203
|
-
|
204
270
|
context "regression test for github issues" do
|
205
|
-
|
206
|
-
it "should not raise undefined method [] for nil:NilClass for objects already saved" do
|
271
|
+
it "should not raise undefined method [] for nil:NilClass when adding a new track into an existing object" do
|
207
272
|
class TestModel
|
208
273
|
include Mongoid::Document
|
209
274
|
include Mongoid::Tracking
|
@@ -220,7 +285,5 @@ describe Mongoid::Tracking do
|
|
220
285
|
tm.something.inc
|
221
286
|
tm.something.today.should == 1
|
222
287
|
end
|
223
|
-
|
224
288
|
end
|
225
|
-
|
226
289
|
end
|
data/trackoid.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{trackoid}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jose Miguel Perez"]
|
12
|
-
s.date = %q{2010-07-
|
12
|
+
s.date = %q{2010-07-16}
|
13
13
|
s.description = %q{Trackoid uses an embeddable approach to track analytics data using the poweful features of MongoDB for scalability}
|
14
14
|
s.email = %q{josemiguel@perezruiz.com}
|
15
15
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trackoid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 6
|
10
|
+
version: 0.1.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jose Miguel Perez
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-07-
|
18
|
+
date: 2010-07-16 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|