trackoid 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|