trackoid 0.1.12 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +29 -3
- data/VERSION +1 -1
- data/lib/trackoid/tracker.rb +49 -8
- data/spec/aggregates_spec.rb +118 -19
- data/trackoid.gemspec +2 -2
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -187,6 +187,27 @@ For comparison, this README is already 8.5Kb in size...
|
|
187
187
|
|
188
188
|
|
189
189
|
= Revision History
|
190
|
+
|
191
|
+
0.2.0 - Added 'reset' and 'erase' methods to tracker fields:
|
192
|
+
* Reset does the same as "set" but also sets aggregate fields.
|
193
|
+
|
194
|
+
Example:
|
195
|
+
|
196
|
+
A) model.value(aggregate_data).set(5)
|
197
|
+
B) model.value(aggregate_data).reset(5)
|
198
|
+
|
199
|
+
A will set "5" to the 'value' and to the aggregate.
|
200
|
+
B will set "5" to the 'value' and all aggregates.
|
201
|
+
|
202
|
+
* Erase resets the values in the mongo database. Note that this
|
203
|
+
is completely different of doing 'reset(0)'. (With erase you
|
204
|
+
can actually recall space from the database).
|
205
|
+
|
206
|
+
- Trackoid now uses "unsafe" mongo update calls from the driver.
|
207
|
+
Note that despite the name, trackoid is absolutely safe, the only
|
208
|
+
diference is that 'update' simply now returns inmediately, without
|
209
|
+
waiting for the OK response from the database.
|
210
|
+
|
190
211
|
0.1.12 - Previously known as "accessors" methods, now they are promoted as
|
191
212
|
"Reader" methods and now they live in its own Module.
|
192
213
|
(Accessor methods are those like "today", "on", "last_days", etc,
|
@@ -198,14 +219,15 @@ For comparison, this README is already 8.5Kb in size...
|
|
198
219
|
0.1.10 - Renamed accessor methods from "all", "last", "first" to
|
199
220
|
"all_values", "first_value" and "last_value" so as not to
|
200
221
|
conflict with traditional ActiveRecord accessors.
|
222
|
+
|
201
223
|
- Aggregate methods with a key returns a single instance, not an
|
202
224
|
Array. For example:
|
203
|
-
|
225
|
+
|
204
226
|
@page.visits.browser("mozilla").today
|
205
227
|
# Returns now a number instead of an Array
|
206
228
|
|
207
229
|
- Arguments are now passed thru aggregator accessors. For example:
|
208
|
-
|
230
|
+
|
209
231
|
@page.visits.brosers("mozilla").last_days(15)
|
210
232
|
# Should correctly return now an array with 15 elements.
|
211
233
|
|
@@ -219,7 +241,11 @@ For comparison, this README is already 8.5Kb in size...
|
|
219
241
|
|
220
242
|
0.1.6 - Enabled support for String dates in operators. This string date
|
221
243
|
must be DateTime parseable.
|
222
|
-
|
244
|
+
|
245
|
+
Example:
|
246
|
+
|
247
|
+
@spain.world_cups.inc("2010-07-11")
|
248
|
+
|
223
249
|
- Normalized Date and DateTime objects to use only Date methods.
|
224
250
|
- Added "first" / "first_date" / "last" / "last_date" accessors.
|
225
251
|
- Added "all" accessor.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/trackoid/tracker.rb
CHANGED
@@ -48,7 +48,7 @@ module Mongoid #:nodoc:
|
|
48
48
|
@owner.collection.update(
|
49
49
|
@owner._selector,
|
50
50
|
{ (how_much > 0 ? "$inc" : "$dec") => update_hash(how_much.abs, date) },
|
51
|
-
:upsert => true
|
51
|
+
:upsert => true, :safe => false
|
52
52
|
)
|
53
53
|
return unless @owner.aggregated?
|
54
54
|
|
@@ -59,7 +59,7 @@ module Mongoid #:nodoc:
|
|
59
59
|
@owner.aggregate_klass.collection.update(
|
60
60
|
selector,
|
61
61
|
{ (how_much > 0 ? "$inc" : "$dec") => update_hash(how_much.abs, date) },
|
62
|
-
:upsert => true
|
62
|
+
:upsert => true, :safe => false
|
63
63
|
)
|
64
64
|
end
|
65
65
|
end
|
@@ -76,9 +76,8 @@ module Mongoid #:nodoc:
|
|
76
76
|
raise Errors::ModelNotSaved, "Can't update a new record" if @owner.new_record?
|
77
77
|
update_data(how_much, date)
|
78
78
|
@owner.collection.update(
|
79
|
-
@owner._selector,
|
80
|
-
|
81
|
-
:upsert => true
|
79
|
+
@owner._selector, { "$set" => update_hash(how_much, date) },
|
80
|
+
:upsert => true, :safe => false
|
82
81
|
)
|
83
82
|
return unless @owner.aggregated?
|
84
83
|
|
@@ -87,9 +86,51 @@ module Mongoid #:nodoc:
|
|
87
86
|
fk = @owner.class.name.to_s.foreign_key.to_sym
|
88
87
|
selector = { fk => @owner.id, :ns => k, :key => token.to_s }
|
89
88
|
@owner.aggregate_klass.collection.update(
|
90
|
-
selector,
|
91
|
-
|
92
|
-
|
89
|
+
selector, { "$set" => update_hash(how_much, date) },
|
90
|
+
:upsert => true, :safe => false
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def reset(how_much, date = Date.today)
|
96
|
+
return erase(date) if how_much.nil?
|
97
|
+
|
98
|
+
# First, we use the default "set" for the tracking field
|
99
|
+
# This will also update one aggregate but... oh well...
|
100
|
+
set(how_much, date)
|
101
|
+
|
102
|
+
# Need to iterate over all aggregates and send an update or delete
|
103
|
+
# operations over all mongo records for this aggregate field
|
104
|
+
@owner.aggregate_fields.each do |(k,v)|
|
105
|
+
fk = @owner.class.name.to_s.foreign_key.to_sym
|
106
|
+
selector = { fk => @owner.id, :ns => k }
|
107
|
+
@owner.aggregate_klass.collection.update(
|
108
|
+
selector, { "$set" => update_hash(how_much, date) },
|
109
|
+
:upsert => true, :multi => true, :safe => false
|
110
|
+
)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def erase(date = Date.today)
|
115
|
+
raise Errors::ModelNotSaved, "Can't update a new record" if @owner.new_record?
|
116
|
+
|
117
|
+
# For the in memory data, we just need to set it to nil
|
118
|
+
update_data(nil, date)
|
119
|
+
@owner.collection.update(
|
120
|
+
@owner._selector,
|
121
|
+
{ "$unset" => update_hash(1, date) },
|
122
|
+
:upsert => true, :safe => false
|
123
|
+
)
|
124
|
+
return unless @owner.aggregated?
|
125
|
+
|
126
|
+
# Need to iterate over all aggregates and send an update or delete
|
127
|
+
# operations over all mongo records
|
128
|
+
@owner.aggregate_fields.each do |(k,v)|
|
129
|
+
fk = @owner.class.name.to_s.foreign_key.to_sym
|
130
|
+
selector = { fk => @owner.id, :ns => k }
|
131
|
+
@owner.aggregate_klass.collection.update(
|
132
|
+
selector, { "$unset" => update_hash(1, date) },
|
133
|
+
:upsert => true, :multi => true, :safe => false
|
93
134
|
)
|
94
135
|
end
|
95
136
|
end
|
data/spec/aggregates_spec.rb
CHANGED
@@ -158,7 +158,7 @@ describe Mongoid::Tracking::Aggregates do
|
|
158
158
|
@object_id = SecondTestModel.first.id
|
159
159
|
@mock = SecondTestModel.find(@object_id)
|
160
160
|
end
|
161
|
-
|
161
|
+
|
162
162
|
it "should correctly save all aggregation keys as strings (inc)" do
|
163
163
|
@mock.something("test").inc
|
164
164
|
@mock.something.aggregate_one.first.key.is_a?(String).should be_true
|
@@ -174,7 +174,6 @@ describe Mongoid::Tracking::Aggregates do
|
|
174
174
|
@mock.something.aggregate_three.first.key.is_a?(String).should be_true
|
175
175
|
@mock.something.aggregate_four.first.key.is_a?(String).should be_true
|
176
176
|
end
|
177
|
-
|
178
177
|
end
|
179
178
|
|
180
179
|
describe "when tracking a model with aggregation data" do
|
@@ -233,8 +232,8 @@ describe Mongoid::Tracking::Aggregates do
|
|
233
232
|
|
234
233
|
it "should work adding 1 visit with different aggregation data" do
|
235
234
|
@mock.visits("Google Chrome").inc
|
236
|
-
@mock.visits.browsers.today.should
|
237
|
-
@mock.visits.referers.today.should
|
235
|
+
@mock.visits.browsers.today.should =~ [["mozilla", 1], ["google", 1]]
|
236
|
+
@mock.visits.referers.today.should =~ [["firefox", 1], ["chrome", 1]]
|
238
237
|
|
239
238
|
# Just for testing array manipulations
|
240
239
|
@mock.visits.browsers.today.inject(0) {|total, c| total + c.last }.should == 2
|
@@ -246,22 +245,22 @@ describe Mongoid::Tracking::Aggregates do
|
|
246
245
|
|
247
246
|
it "should work also with set" do
|
248
247
|
@mock.visits("Google Chrome").set(5)
|
249
|
-
@mock.visits.browsers.today.should
|
250
|
-
@mock.visits.referers.today.should
|
248
|
+
@mock.visits.browsers.today.should =~ [["mozilla", 1], ["google", 5]]
|
249
|
+
@mock.visits.referers.today.should =~ [["firefox", 1], ["chrome", 5]]
|
251
250
|
@mock.visits.today.should == 5
|
252
251
|
end
|
253
252
|
|
254
253
|
it "let's check what happens when sorting the best browser..." do
|
255
254
|
@mock.visits("Google Chrome").inc
|
256
|
-
@mock.visits.browsers.today.should
|
255
|
+
@mock.visits.browsers.today.should =~ [["mozilla", 1], ["google", 6]]
|
257
256
|
@mock.visits.browsers.today.max {|a,b| a.second <=> b.second }.should == ["google", 6]
|
258
257
|
end
|
259
258
|
|
260
259
|
it "should work without aggregation information" do
|
261
260
|
@mock.visits.inc
|
262
|
-
@mock.visits.browsers.today.should
|
263
|
-
@mock.visits.referers.today.should
|
264
|
-
|
261
|
+
@mock.visits.browsers.today.should =~ [["mozilla", 1], ["google", 6]]
|
262
|
+
@mock.visits.referers.today.should =~ [["firefox", 1], ["chrome", 6]]
|
263
|
+
|
265
264
|
# A more throughout test would check totals...
|
266
265
|
visits_today = @mock.visits.today
|
267
266
|
visits_today_with_browser = @mock.visits.browsers.today.inject(0) {|total, c| total + c.last }
|
@@ -269,6 +268,107 @@ describe Mongoid::Tracking::Aggregates do
|
|
269
268
|
end
|
270
269
|
end
|
271
270
|
|
271
|
+
describe "When using reset method for aggregates" do
|
272
|
+
before do
|
273
|
+
TestModel.all.map(&:destroy)
|
274
|
+
TestModel.create(:name => "test")
|
275
|
+
|
276
|
+
@object_id = TestModel.first.id
|
277
|
+
@mock = TestModel.first
|
278
|
+
|
279
|
+
@mock.visits("Mozilla Firefox").set(1, "2010-07-11")
|
280
|
+
@mock.visits("Google Chrome").set(2, "2010-07-11")
|
281
|
+
@mock.visits("Internet Explorer").set(3, "2010-07-11")
|
282
|
+
|
283
|
+
@mock.visits("Mozilla Firefox").set(4, "2010-07-14")
|
284
|
+
@mock.visits("Google Chrome").set(5, "2010-07-14")
|
285
|
+
@mock.visits("Internet Explorer").set(6, "2010-07-14")
|
286
|
+
|
287
|
+
@mock.uniques("Mozilla Firefox").set(1, "2010-07-11")
|
288
|
+
@mock.uniques("Google Chrome").set(2, "2010-07-11")
|
289
|
+
@mock.uniques("Internet Explorer").set(3, "2010-07-11")
|
290
|
+
|
291
|
+
@mock.uniques("Mozilla Firefox").set(4, "2010-07-14")
|
292
|
+
@mock.uniques("Google Chrome").set(5, "2010-07-14")
|
293
|
+
@mock.uniques("Internet Explorer").set(6, "2010-07-14")
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should have the correct values when using a value" do
|
297
|
+
@mock.visits.reset(99, "2010-07-14")
|
298
|
+
|
299
|
+
@mock.visits.on("2010-07-14").should == 99
|
300
|
+
@mock.visits.browsers.all_values.should =~ [
|
301
|
+
["mozilla", [1, 0, 0, 99]],
|
302
|
+
["google", [2, 0, 0, 99]],
|
303
|
+
["internet", [3, 0, 0, 99]]
|
304
|
+
]
|
305
|
+
@mock.visits.referers.all_values.should =~ [
|
306
|
+
["firefox", [1, 0, 0, 99]],
|
307
|
+
["chrome", [2, 0, 0, 99]],
|
308
|
+
["explorer", [3, 0, 0, 99]]
|
309
|
+
]
|
310
|
+
end
|
311
|
+
|
312
|
+
it "should delete the values when using nil" do
|
313
|
+
@mock.visits.reset(nil, "2010-07-14")
|
314
|
+
|
315
|
+
@mock.visits.on("2010-07-14").should == 0
|
316
|
+
@mock.visits.browsers.all_values.should =~ [
|
317
|
+
["mozilla", [1]],
|
318
|
+
["google", [2]],
|
319
|
+
["internet", [3]]
|
320
|
+
]
|
321
|
+
@mock.visits.referers.all_values.should =~ [
|
322
|
+
["firefox", [1]],
|
323
|
+
["chrome", [2]],
|
324
|
+
["explorer", [3]]
|
325
|
+
]
|
326
|
+
end
|
327
|
+
|
328
|
+
it "erase method sould also work" do
|
329
|
+
@mock.visits.erase("2010-07-14")
|
330
|
+
|
331
|
+
@mock.visits.on("2010-07-14").should == 0
|
332
|
+
@mock.visits.browsers.all_values.should =~ [
|
333
|
+
["mozilla", [1]],
|
334
|
+
["google", [2]],
|
335
|
+
["internet", [3]]
|
336
|
+
]
|
337
|
+
end
|
338
|
+
|
339
|
+
it "should reset the correct tracking fields" do
|
340
|
+
@mock.visits.reset(99, "2010-07-14")
|
341
|
+
|
342
|
+
@mock.uniques.on("2010-07-14").should == 6
|
343
|
+
@mock.uniques.browsers.all_values.should =~ [
|
344
|
+
["mozilla", [1, 0, 0, 4]],
|
345
|
+
["google", [2, 0, 0, 5]],
|
346
|
+
["internet", [3, 0, 0, 6]]
|
347
|
+
]
|
348
|
+
@mock.uniques.referers.all_values.should =~ [
|
349
|
+
["firefox", [1, 0, 0, 4]],
|
350
|
+
["chrome", [2, 0, 0, 5]],
|
351
|
+
["explorer", [3, 0, 0, 6]]
|
352
|
+
]
|
353
|
+
end
|
354
|
+
|
355
|
+
it "should erase the correct tracking fields" do
|
356
|
+
@mock.visits.erase("2010-07-14")
|
357
|
+
|
358
|
+
@mock.uniques.on("2010-07-14").should == 6
|
359
|
+
@mock.uniques.browsers.all_values.should =~ [
|
360
|
+
["mozilla", [1, 0, 0, 4]],
|
361
|
+
["google", [2, 0, 0, 5]],
|
362
|
+
["internet", [3, 0, 0, 6]]
|
363
|
+
]
|
364
|
+
@mock.uniques.referers.all_values.should =~ [
|
365
|
+
["firefox", [1, 0, 0, 4]],
|
366
|
+
["chrome", [2, 0, 0, 5]],
|
367
|
+
["explorer", [3, 0, 0, 6]]
|
368
|
+
]
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
272
372
|
describe "Testing all accessors" do
|
273
373
|
before do
|
274
374
|
TestModel.all.map(&:destroy)
|
@@ -280,7 +380,7 @@ describe Mongoid::Tracking::Aggregates do
|
|
280
380
|
@mock.visits("Mozilla Firefox").set(1, "2010-07-11")
|
281
381
|
@mock.visits("Google Chrome").set(2, "2010-07-12")
|
282
382
|
@mock.visits("Internet Explorer").set(3, "2010-07-13")
|
283
|
-
|
383
|
+
|
284
384
|
# For 'last' values
|
285
385
|
@mock.visits("Mozilla Firefox").set(4, "2010-07-14")
|
286
386
|
@mock.visits("Google Chrome").set(5, "2010-07-15")
|
@@ -290,17 +390,17 @@ describe Mongoid::Tracking::Aggregates do
|
|
290
390
|
it "should return the correct values for .all_values" do
|
291
391
|
@mock.visits.all_values.should == [1, 2, 3, 4, 5, 6]
|
292
392
|
end
|
293
|
-
|
393
|
+
|
294
394
|
it "should return the all values for every aggregate" do
|
295
|
-
@mock.visits.browsers.all_values.should
|
395
|
+
@mock.visits.browsers.all_values.should =~ [
|
296
396
|
["mozilla", [1, 0, 0, 4]],
|
297
397
|
["google", [2, 0, 0, 5]],
|
298
398
|
["internet", [3, 0, 0, 6]]
|
299
399
|
]
|
300
400
|
end
|
301
|
-
|
401
|
+
|
302
402
|
it "should return the correct first_date for every aggregate" do
|
303
|
-
@mock.visits.browsers.first_date.should
|
403
|
+
@mock.visits.browsers.first_date.should =~ [
|
304
404
|
["mozilla", Date.parse("2010-07-11")],
|
305
405
|
["google", Date.parse("2010-07-12")],
|
306
406
|
["internet", Date.parse("2010-07-13")]
|
@@ -308,7 +408,7 @@ describe Mongoid::Tracking::Aggregates do
|
|
308
408
|
end
|
309
409
|
|
310
410
|
it "should return the correct last_date for every aggregate" do
|
311
|
-
@mock.visits.browsers.last_date.should
|
411
|
+
@mock.visits.browsers.last_date.should =~ [
|
312
412
|
["mozilla", Date.parse("2010-07-14")],
|
313
413
|
["google", Date.parse("2010-07-15")],
|
314
414
|
["internet", Date.parse("2010-07-16")]
|
@@ -316,7 +416,7 @@ describe Mongoid::Tracking::Aggregates do
|
|
316
416
|
end
|
317
417
|
|
318
418
|
it "should return the first value for aggregates" do
|
319
|
-
@mock.visits.browsers.first_value.should
|
419
|
+
@mock.visits.browsers.first_value.should =~ [
|
320
420
|
["mozilla", 1],
|
321
421
|
["google", 2],
|
322
422
|
["internet", 3]
|
@@ -324,12 +424,11 @@ describe Mongoid::Tracking::Aggregates do
|
|
324
424
|
end
|
325
425
|
|
326
426
|
it "should return the last value for aggregates" do
|
327
|
-
@mock.visits.browsers.last_value.should
|
427
|
+
@mock.visits.browsers.last_value.should =~ [
|
328
428
|
["mozilla", 4],
|
329
429
|
["google", 5],
|
330
430
|
["internet", 6]
|
331
431
|
]
|
332
432
|
end
|
333
|
-
|
334
433
|
end
|
335
434
|
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.
|
8
|
+
s.version = "0.2.0"
|
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{2011-03-
|
12
|
+
s.date = %q{2011-03-26}
|
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
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jose Miguel Perez
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-03-
|
17
|
+
date: 2011-03-26 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|