trackoid 0.1.8 → 0.1.9
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 +5 -0
- data/VERSION +1 -1
- data/lib/trackoid/aggregates.rb +1 -1
- data/lib/trackoid/tracker.rb +16 -8
- data/lib/trackoid/tracker_aggregates.rb +15 -35
- data/spec/aggregates_spec.rb +94 -14
- data/trackoid.gemspec +2 -2
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -187,6 +187,11 @@ For comparison, this README is already 8.5Kb in size.
|
|
187
187
|
|
188
188
|
= Revision History
|
189
189
|
|
190
|
+
0.1.9 - Refactored TrackerAggregates to include all accessor methods
|
191
|
+
(all, last, first, etc.)
|
192
|
+
|
193
|
+
0.1.8 - Another maintenance release. Sorry. :-)
|
194
|
+
|
190
195
|
0.1.7 - Maintenance Release: A little error with the index on aggregated fields
|
191
196
|
|
192
197
|
0.1.6 - Enabled support for String dates in operators. This string date must
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.9
|
data/lib/trackoid/aggregates.rb
CHANGED
data/lib/trackoid/tracker.rb
CHANGED
@@ -35,18 +35,22 @@ module Mongoid #:nodoc:
|
|
35
35
|
def add(how_much = 1, date = Date.today)
|
36
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
|
-
@owner.collection.update(
|
38
|
+
@owner.collection.update(
|
39
|
+
@owner._selector,
|
39
40
|
{ (how_much > 0 ? "$inc" : "$dec") => update_hash(how_much.abs, date) },
|
40
|
-
:upsert => true
|
41
|
+
:upsert => true
|
42
|
+
)
|
41
43
|
return unless @owner.aggregated?
|
42
44
|
|
43
45
|
@owner.aggregate_fields.each do |(k,v)|
|
44
46
|
next unless token = v.call(@aggregate_data)
|
45
47
|
fk = @owner.class.name.to_s.foreign_key.to_sym
|
46
48
|
selector = { fk => @owner.id, :ns => k, :key => token.to_s }
|
47
|
-
@owner.aggregate_klass.collection.update(
|
49
|
+
@owner.aggregate_klass.collection.update(
|
50
|
+
selector,
|
48
51
|
{ (how_much > 0 ? "$inc" : "$dec") => update_hash(how_much.abs, date) },
|
49
|
-
:upsert => true
|
52
|
+
:upsert => true
|
53
|
+
)
|
50
54
|
end
|
51
55
|
end
|
52
56
|
|
@@ -61,18 +65,22 @@ module Mongoid #:nodoc:
|
|
61
65
|
def set(how_much, date = Date.today)
|
62
66
|
raise Errors::ModelNotSaved, "Can't update a new record" if @owner.new_record?
|
63
67
|
update_data(how_much, date)
|
64
|
-
@owner.collection.update(
|
68
|
+
@owner.collection.update(
|
69
|
+
@owner._selector,
|
65
70
|
{ "$set" => update_hash(how_much, date) },
|
66
|
-
:upsert => true
|
71
|
+
:upsert => true
|
72
|
+
)
|
67
73
|
return unless @owner.aggregated?
|
68
74
|
|
69
75
|
@owner.aggregate_fields.each do |(k,v)|
|
70
76
|
next unless token = v.call(@aggregate_data)
|
71
77
|
fk = @owner.class.name.to_s.foreign_key.to_sym
|
72
78
|
selector = { fk => @owner.id, :ns => k, :key => token.to_s }
|
73
|
-
@owner.aggregate_klass.collection.update(
|
79
|
+
@owner.aggregate_klass.collection.update(
|
80
|
+
selector,
|
74
81
|
{ "$set" => update_hash(how_much, date) },
|
75
|
-
:upsert => true
|
82
|
+
:upsert => true
|
83
|
+
)
|
76
84
|
end
|
77
85
|
end
|
78
86
|
|
@@ -15,49 +15,29 @@ module Mongoid #:nodoc:
|
|
15
15
|
@criteria = @owner.send(@accessor).where(@selector)
|
16
16
|
end
|
17
17
|
|
18
|
-
# REFACTOR THIS
|
19
|
-
# WE ARE DOING SOMETHING LIKE:
|
20
|
-
#
|
21
|
-
# => browsers("something").visits
|
22
|
-
#
|
23
|
-
# WHILE A BEST APPROACH IS LIKE
|
24
|
-
#
|
25
|
-
# => visits.browsers("something")
|
26
|
-
|
27
|
-
# visits (Tracker) -> browsers (TrackerAggregates) -> count (to Criteria)
|
28
|
-
# -> today (data)
|
29
|
-
|
30
18
|
# Delegate all missing methods to the underlying Mongoid Criteria
|
31
19
|
def method_missing(name, *args, &block)
|
32
20
|
@criteria.send(name)
|
33
|
-
|
34
|
-
# Delegate all missing methods to the underlying Mongoid Criteria
|
35
|
-
# return @criteria.send(name) unless @owner.tracked_fields.member?(name)
|
36
|
-
# super
|
37
|
-
|
38
|
-
# Otherwise, it's a track method, so process it
|
39
|
-
# @criteria.collect {|x| x.send(name, *args, &block) }
|
40
21
|
end
|
41
22
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
23
|
+
# Access the aggregation collection with "collection" so that we can
|
24
|
+
# use the original mongoid methods like "all", "first", etc.
|
25
|
+
def collection
|
26
|
+
@criteria
|
46
27
|
end
|
47
28
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
29
|
+
# Define all accessors here. Basically we are delegating to the Track
|
30
|
+
# object for every object in the criteria
|
31
|
+
[ :today, :yesterday, :last_days, :all, :first, :last,
|
32
|
+
:first_date, :last_date
|
33
|
+
].each {|name|
|
34
|
+
define_method(name) do |*args|
|
35
|
+
@criteria.collect {|c|
|
36
|
+
[c.key, c.send(@track_field).send(name)] if @track_field
|
37
|
+
}
|
38
|
+
end
|
39
|
+
}
|
59
40
|
|
60
41
|
end
|
61
|
-
|
62
42
|
end
|
63
43
|
end
|
data/spec/aggregates_spec.rb
CHANGED
@@ -21,11 +21,12 @@ class SecondTestModel
|
|
21
21
|
include Mongoid::Tracking
|
22
22
|
|
23
23
|
field :name # Dummy field
|
24
|
-
track :
|
24
|
+
track :something
|
25
25
|
|
26
|
-
aggregate :
|
27
|
-
|
28
|
-
end
|
26
|
+
aggregate :aggregate_one do 1 end
|
27
|
+
aggregate :aggregate_two do "p" end
|
28
|
+
aggregate :aggregate_three do BSON::ObjectID.new("4c4121857bc3cd0d78cb65b2") end
|
29
|
+
aggregate :aggregate_four do Time.now end
|
29
30
|
end
|
30
31
|
|
31
32
|
describe Mongoid::Tracking::Aggregates do
|
@@ -150,10 +151,35 @@ describe Mongoid::Tracking::Aggregates do
|
|
150
151
|
}.should raise_error Mongoid::Errors::ClassAlreadyDefined
|
151
152
|
end
|
152
153
|
|
153
|
-
describe "
|
154
|
+
describe "testing different object class for aggregation key" do
|
155
|
+
before do
|
156
|
+
SecondTestModel.all.map(&:destroy)
|
157
|
+
SecondTestModel.create(:name => "test")
|
158
|
+
@object_id = SecondTestModel.first.id
|
159
|
+
@mock = SecondTestModel.find(@object_id)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should correctly save all aggregation keys as strings (inc)" do
|
163
|
+
@mock.something("test").inc
|
164
|
+
@mock.something.aggregate_one.collection.first.key.is_a?(String).should be_true
|
165
|
+
@mock.something.aggregate_two.collection.first.key.is_a?(String).should be_true
|
166
|
+
@mock.something.aggregate_three.collection.first.key.is_a?(String).should be_true
|
167
|
+
@mock.something.aggregate_four.collection.first.key.is_a?(String).should be_true
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should correctly save all aggregation keys as strings (set)" do
|
171
|
+
@mock.something("test").set(5)
|
172
|
+
@mock.something.aggregate_one.collection.first.key.is_a?(String).should be_true
|
173
|
+
@mock.something.aggregate_two.collection.first.key.is_a?(String).should be_true
|
174
|
+
@mock.something.aggregate_three.collection.first.key.is_a?(String).should be_true
|
175
|
+
@mock.something.aggregate_four.collection.first.key.is_a?(String).should be_true
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
154
179
|
|
180
|
+
describe "when tracking a model with aggregation data" do
|
155
181
|
before(:all) do
|
156
|
-
TestModel.
|
182
|
+
TestModel.all.map(&:destroy)
|
157
183
|
TestModel.create(:name => "test")
|
158
184
|
@object_id = TestModel.first.id
|
159
185
|
end
|
@@ -216,7 +242,7 @@ describe Mongoid::Tracking::Aggregates do
|
|
216
242
|
@mock.visits.today.should == 5
|
217
243
|
end
|
218
244
|
|
219
|
-
it "let's
|
245
|
+
it "let's check what happens when sorting the best browser..." do
|
220
246
|
@mock.visits("Google Chrome").inc
|
221
247
|
@mock.visits.browsers.today.should == [["mozilla", 1], ["google", 6]]
|
222
248
|
@mock.visits.browsers.today.max {|a,b| a.second <=> b.second }.should == ["google", 6]
|
@@ -232,15 +258,69 @@ describe Mongoid::Tracking::Aggregates do
|
|
232
258
|
visits_today_with_browser = @mock.visits.browsers.today.inject(0) {|total, c| total + c.last }
|
233
259
|
visits_today.should == visits_today_with_browser
|
234
260
|
end
|
235
|
-
|
236
261
|
end
|
237
262
|
|
263
|
+
describe "Testing all accessors" do
|
264
|
+
before do
|
265
|
+
TestModel.all.map(&:destroy)
|
266
|
+
TestModel.create(:name => "test")
|
267
|
+
@object_id = TestModel.first.id
|
268
|
+
@mock = TestModel.first
|
269
|
+
|
270
|
+
# For 'first' values
|
271
|
+
@mock.visits("Mozilla Firefox").set(1, "2010-07-11")
|
272
|
+
@mock.visits("Google Chrome").set(2, "2010-07-12")
|
273
|
+
@mock.visits("Internet Explorer").set(3, "2010-07-13")
|
274
|
+
|
275
|
+
# For 'last' values
|
276
|
+
@mock.visits("Mozilla Firefox").set(4, "2010-07-14")
|
277
|
+
@mock.visits("Google Chrome").set(5, "2010-07-15")
|
278
|
+
@mock.visits("Internet Explorer").set(6, "2010-07-16")
|
279
|
+
end
|
238
280
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
281
|
+
it "should return the correct values for .all" do
|
282
|
+
@mock.visits.all.should == [1, 2, 3, 4, 5, 6]
|
283
|
+
end
|
284
|
+
|
285
|
+
it "should return the all values for every aggregate" do
|
286
|
+
@mock.visits.browsers.all.should == [
|
287
|
+
["mozilla", [1, 0, 0, 4]],
|
288
|
+
["google", [2, 0, 0, 5]],
|
289
|
+
["internet", [3, 0, 0, 6]]
|
290
|
+
]
|
291
|
+
end
|
292
|
+
|
293
|
+
it "should return the correct first_date for every aggregate" do
|
294
|
+
@mock.visits.browsers.first_date.should == [
|
295
|
+
["mozilla", Date.parse("2010-07-11")],
|
296
|
+
["google", Date.parse("2010-07-12")],
|
297
|
+
["internet", Date.parse("2010-07-13")]
|
298
|
+
]
|
299
|
+
end
|
245
300
|
|
301
|
+
it "should return the correct last_date for every aggregate" do
|
302
|
+
@mock.visits.browsers.last_date.should == [
|
303
|
+
["mozilla", Date.parse("2010-07-14")],
|
304
|
+
["google", Date.parse("2010-07-15")],
|
305
|
+
["internet", Date.parse("2010-07-16")]
|
306
|
+
]
|
307
|
+
end
|
308
|
+
|
309
|
+
it "should return the first value for aggregates" do
|
310
|
+
@mock.visits.browsers.first.should == [
|
311
|
+
["mozilla", 1],
|
312
|
+
["google", 2],
|
313
|
+
["internet", 3]
|
314
|
+
]
|
315
|
+
end
|
316
|
+
|
317
|
+
it "should return the last value for aggregates" do
|
318
|
+
@mock.visits.browsers.last.should == [
|
319
|
+
["mozilla", 4],
|
320
|
+
["google", 5],
|
321
|
+
["internet", 6]
|
322
|
+
]
|
323
|
+
end
|
324
|
+
|
325
|
+
end
|
246
326
|
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.9"
|
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-18}
|
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: 9
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 9
|
10
|
+
version: 0.1.9
|
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-18 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|