trackoid 0.3.8 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,97 @@
1
+ #
2
+ # This is a simple spec to check if tracking works within embedded documents
3
+ # If this passes, the rest of the funcionality it's assumed to work (TZ, etc)
4
+ #
5
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
6
+
7
+ class TestEmbedOne
8
+ include Mongoid::Document
9
+ field :name # Dummy field
10
+ embeds_one :embedded_test
11
+ end
12
+
13
+ class TestEmbedMany
14
+ include Mongoid::Document
15
+ field :name # Dummy field
16
+ embeds_many :embedded_test
17
+ end
18
+
19
+ class EmbeddedTest
20
+ include Mongoid::Document
21
+ include Mongoid::Tracking
22
+ field :name # Dummy field
23
+ track :visits
24
+ embedded_in :test_embed_one
25
+ embedded_in :test_embed_many
26
+ end
27
+
28
+ # And Now For Something Completely Different...
29
+
30
+ class TestEmbedOuter
31
+ include Mongoid::Document
32
+ field :name # Dummy field
33
+ embeds_one :test_embed_middle
34
+ end
35
+
36
+ class TestEmbedMiddle
37
+ include Mongoid::Document
38
+ field :name # Dummy field
39
+ embedded_in :test_embed_outer
40
+ embeds_one :test_embed_final
41
+ end
42
+
43
+ class TestEmbedFinal
44
+ include Mongoid::Document
45
+ include Mongoid::Tracking
46
+ field :name # Dummy field
47
+ track :visits
48
+ embedded_in :test_embed_middle
49
+ end
50
+
51
+
52
+ describe Mongoid::Tracking do
53
+
54
+ # Useful to see all MongoDB operations in place while RSpec is working
55
+ before(:all) do
56
+ # Moped.logger.level = Logger::DEBUG
57
+ end
58
+
59
+ context "within a document which embeds one or more models with tracking" do
60
+ let(:today) { Time.now }
61
+ let(:mock_one) { TestEmbedOne.create(:name => "Parent", :embedded_test => {:name => "Child"}) }
62
+ let(:mock_many) { TestEmbedMany.create(:name => "Parent", :embedded_test => [{:name => "Child1"}, {:name => "Child2"} ]) }
63
+
64
+ it "should have the tracking field working and not bleed to the parent" do
65
+ mock_one.respond_to?(:visits).should be_false
66
+ mock_one.embedded_test.respond_to?(:visits).should be_true
67
+
68
+ mock_many.respond_to?(:visits).should be_false
69
+ mock_many.embedded_test.first.respond_to?(:visits).should be_true
70
+ mock_many.embedded_test.last.respond_to?(:visits).should be_true
71
+ end
72
+
73
+ it "the tracking data should work fine" do
74
+ mock_one.embedded_test.visits.inc(today)
75
+ mock_one.embedded_test.visits.on(today).should == 1
76
+
77
+ mock_many.embedded_test.first.visits.inc(today)
78
+ mock_many.embedded_test.first.visits.on(today).should == 1
79
+ mock_many.embedded_test.last.visits.on(today).should == 0
80
+ end
81
+ end
82
+
83
+ context "within a three level embedded model" do
84
+ let(:today) { Time.now }
85
+ let(:outer) { TestEmbedOuter.create(:name => "Outer", :test_embed_middle => {:name => "Middle", :test_embed_final => { :name => "Final" }}) }
86
+
87
+ it "should just work..." do
88
+ outer.respond_to?(:visits).should be_false
89
+ outer.test_embed_middle.respond_to?(:visits).should be_false
90
+ outer.test_embed_middle.test_embed_final.respond_to?(:visits).should be_true
91
+
92
+ outer.test_embed_middle.test_embed_final.visits.inc(today)
93
+ outer.test_embed_middle.test_embed_final.visits.on(today).should == 1
94
+ outer.test_embed_middle.test_embed_final.visits.on(today - 1.day).should == 0
95
+ end
96
+ end
97
+ end
@@ -1,28 +1,18 @@
1
+ # FIXME: We should modify the load path here.
1
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
3
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
- require 'rubygems'
4
4
 
5
- # What is this doing here?
6
- # gem 'mocha', '>= 0.9.8'
7
-
8
- require 'mocha'
9
5
  require 'mongoid'
10
6
  require 'trackoid'
11
- require 'bson'
12
7
  require 'rspec'
13
8
  require 'rspec/autorun'
14
9
 
15
- Mongoid.configure do |config|
16
- name = "trackoid_test"
17
- host = "localhost"
18
- port = "27017"
19
- # config.master = Mongo::Connection.new(host, port, :logger => Logger.new(STDOUT)).db(name)
20
- config.master = Mongo::Connection.new.db(name)
21
- end
22
-
23
10
  RSpec.configure do |config|
24
- config.mock_with :mocha
25
- config.before :suite do
26
- Mongoid.master.collections.reject { |c| c.name =~ /^system\./ }.each(&:drop)
11
+ config.before(:suite) do
12
+ Mongoid.load!(File.expand_path(File.dirname(__FILE__) + "/../config/mongoid.yml"), :test)
13
+ end
14
+
15
+ config.after(:each) do
16
+ Mongoid::Config.purge!
27
17
  end
28
18
  end
@@ -9,25 +9,21 @@ class Test
9
9
  end
10
10
 
11
11
  describe Mongoid::Tracking do
12
- before(:all) do
13
- @trackoid_version = File.read(File.expand_path("../VERSION", File.dirname(__FILE__)))
12
+ it "should ensure allow_dynamic_fields option is turned off" do
13
+ Mongoid::Config.settings[:allow_dynamic_fields].should == false
14
14
  end
15
15
 
16
- it "should expose the same version as the VERSION file" do
17
- Mongoid::Tracking::VERSION.should == @trackoid_version
18
- end
19
-
20
16
  it "should raise error when used in a class not of class Mongoid::Document" do
21
- lambda {
17
+ -> {
22
18
  class NotMongoidClass
23
19
  include Mongoid::Tracking
24
20
  track :something
25
21
  end
26
- }.should raise_error Mongoid::Errors::NotMongoid
22
+ }.should raise_error Mongoid::Tracking::Errors::NotMongoid
27
23
  end
28
24
 
29
25
  it "should not raise error when used in a class of class Mongoid::Document" do
30
- lambda {
26
+ -> {
31
27
  class MongoidedDocument
32
28
  include Mongoid::Document
33
29
  include Mongoid::Tracking
@@ -37,13 +33,13 @@ describe Mongoid::Tracking do
37
33
  end
38
34
 
39
35
  it "should not raise errors when using to/as_json" do
40
- mock = Test.new(:name => "Trackoid")
36
+ test = Test.new(:name => "Trackoid")
41
37
  json_as = {}
42
38
  json_to = ""
43
39
 
44
- lambda {
45
- json_as = mock.as_json(:except => :_id)
46
- json_to = mock.to_json(:except => :_id)
40
+ -> {
41
+ json_as = test.as_json(:except => :_id)
42
+ json_to = test.to_json(:except => :_id)
47
43
  }.should_not raise_error
48
44
 
49
45
  json_as.should == { "name" => "Trackoid" }
@@ -55,11 +51,6 @@ describe Mongoid::Tracking do
55
51
  @mock = Test.new
56
52
  end
57
53
 
58
- it "should deny access to the underlying mongoid field" do
59
- lambda { @mock.visits_data }.should raise_error NoMethodError
60
- lambda { @mock.visits_data = {} }.should raise_error NoMethodError
61
- end
62
-
63
54
  it "should create a method for accesing the stats" do
64
55
  @mock.respond_to?(:visits).should be_true
65
56
  end
@@ -68,12 +59,6 @@ describe Mongoid::Tracking do
68
59
  @mock.class.index_options.should_not include(:visits_data)
69
60
  end
70
61
 
71
- it "should respond 'false' to field_changed? method" do
72
- # Ok, this test is not very relevant since it will return false even
73
- # if Trackoid does not override it.
74
- @mock.visits_changed?.should be_false
75
- end
76
-
77
62
  it "should create a method for accesing the stats of the proper class" do
78
63
  @mock.visits.class.should == Mongoid::Tracking::Tracker
79
64
  end
@@ -90,7 +75,7 @@ describe Mongoid::Tracking do
90
75
  end
91
76
 
92
77
  it "should not update stats when new record" do
93
- lambda { @mock.visits.inc }.should raise_error Mongoid::Errors::ModelNotSaved
78
+ -> { @mock.visits.inc }.should raise_error Mongoid::Tracking::Errors::ModelNotSaved
94
79
  end
95
80
 
96
81
  it "should create an empty hash as the internal representation" do
@@ -113,126 +98,137 @@ describe Mongoid::Tracking do
113
98
  @mock.aggregated?.should be_false
114
99
  end
115
100
  end
116
-
101
+
117
102
  describe "when using a model in the database" do
118
- before(:all) do
119
- Test.delete_all
120
- Test.create(:name => "test")
121
- @object_id = Test.first.id
122
- end
103
+ let(:test) { Test.create(:name => "test") }
123
104
 
124
105
  before do
125
- @mock = Test.find(@object_id)
126
106
  @today = Time.now
127
107
  end
128
108
 
129
109
  it "should increment visits stats for today" do
130
- @mock.visits.inc
131
- @mock.visits.today.should == 1
110
+ test.visits.inc
111
+ test.visits.today.should == 1
132
112
  end
133
113
 
134
114
  it "should increment another visits stats for today for a total of 2" do
135
- @mock.visits.inc
136
- @mock.visits.today.should == 2
115
+ test.visits.inc
116
+ test.visits.inc
117
+ test.visits.today.should == 2
137
118
  end
138
119
 
139
120
  it "should also work for yesterday" do
140
- @mock.visits.inc(@today - 1.day)
141
- @mock.visits.yesterday.should == 1
121
+ test.visits.inc(@today - 1.day)
122
+ test.visits.yesterday.should == 1
142
123
  end
143
124
 
144
125
  it "should also work for yesterday if adding another visit (for a total of 2)" do
145
- @mock.visits.inc(@today - 1.day)
146
- @mock.visits.yesterday.should == 2
126
+ test.visits.inc(@today - 1.day)
127
+ test.visits.inc(@today - 1.day)
128
+ test.visits.yesterday.should == 2
147
129
  end
148
-
130
+
149
131
  it "then, the visits of today + yesterday must be the same" do
150
- @mock.visits.last_days(2).should == [2, 2]
132
+ test.visits.inc
133
+ test.visits.inc
134
+ test.visits.inc(@today - 1.day)
135
+ test.visits.inc(@today - 1.day)
136
+ test.visits.last_days(2).should == [2, 2]
151
137
  end
152
138
 
153
139
  it "should have 4 visits for this test" do
154
- @mock.visits.last_days(2).sum.should == 4
140
+ test.visits.inc
141
+ test.visits.inc
142
+ test.visits.inc(@today - 1.day)
143
+ test.visits.inc(@today - 1.day)
144
+ test.visits.last_days(2).sum.should == 4
155
145
  end
156
146
 
157
147
  it "should correctly handle the 7 days" do
158
- @mock.visits.last_days.should == [0, 0, 0, 0, 0, 2, 2]
148
+ test.visits.inc
149
+ test.visits.inc
150
+ test.visits.inc(@today - 1.day)
151
+ test.visits.inc(@today - 1.day)
152
+ test.visits.last_days.should == [0, 0, 0, 0, 0, 2, 2]
159
153
  end
160
154
 
161
155
  it "string dates should work" do
162
- @mock.visits.inc("2010-07-11")
163
- @mock.visits.on("2010-07-11").should == 1
156
+ test.visits.inc("2010-07-11")
157
+ test.visits.on("2010-07-11").should == 1
164
158
  end
165
159
 
166
160
  it "should give the first date with first_date" do
161
+ test.visits.inc("2010-07-11")
167
162
  t = Time.parse("2010-07-11")
168
- f = @mock.visits.first_date
163
+ f = test.visits.first_date
169
164
  [f.year, f.month, f.day, f.hour].should == [t.year, t.month, t.day, t.hour]
170
165
  end
171
166
 
172
167
  it "should give the last date with last_date" do
173
168
  future = @today + 1.month
174
- @mock.visits.set(22, future)
175
- f = @mock.visits.last_date
169
+ test.visits.set(22, future)
170
+ f = test.visits.last_date
176
171
  [f.year, f.month, f.day, f.hour].should == [future.year, future.month, future.day, future.hour]
177
172
  end
178
173
 
179
174
  it "should give the first value" do
180
- @mock.visits.first_value.should == 1
175
+ test.visits.inc("2010-07-11")
176
+ test.visits.first_value.should == 1
181
177
  end
182
178
 
183
179
  it "should give the last value" do
184
- @mock.visits.last_value.should == 22
180
+ future = @today + 1.month
181
+ test.visits.set(22, future)
182
+ test.visits.last_value.should == 22
185
183
  end
186
184
  end
187
185
 
188
186
  context "testing reader operations without reloading models" do
189
- before(:all) do
190
- Test.delete_all
191
- Test.create(:name => "test")
192
- @object_id = Test.first.id
193
- end
194
-
195
- before do
196
- @mock = Test.find(@object_id)
197
- end
187
+ let(:test) { Test.create(name: "test") }
188
+ let(:object_id) { test.id }
198
189
 
199
190
  it "'set' operator must work" do
200
- @mock.visits.set(5)
201
- @mock.visits.today.should == 5
202
- Test.find(@object_id).visits.today.should == 5
191
+ test.visits.set(5)
192
+ test.visits.today.should == 5
193
+ Test.find(object_id).visits.today.should == 5
203
194
  end
204
195
 
205
196
  it "'set' operator must work on arbitrary days" do
206
- @mock.visits.set(5, Time.parse("2010-05-01"))
207
- @mock.visits.on(Time.parse("2010-05-01")).should == 5
208
- Test.find(@object_id).visits.on(Time.parse("2010-05-01")).should == 5
197
+ test.visits.set(5, Time.parse("2010-05-01"))
198
+ test.visits.on(Time.parse("2010-05-01")).should == 5
199
+ Test.find(object_id).visits.on(Time.parse("2010-05-01")).should == 5
209
200
  end
210
201
 
211
202
  it "'add' operator must work" do
212
- @mock.visits.add(5)
213
- @mock.visits.today.should == 10 # Remember 5 set on previous test
214
- Test.find(@object_id).visits.today.should == 10
203
+ test.visits.set(5)
204
+ test.visits.add(5)
205
+ test.visits.today.should == 10
206
+ Test.find(object_id).visits.today.should == 10
215
207
  end
216
208
 
217
209
  it "'add' operator must work on arbitrary days" do
218
- @mock.visits.add(5, Time.parse("2010-05-01"))
219
- @mock.visits.on(Time.parse("2010-05-01")).should == 10
220
- Test.find(@object_id).visits.on(Time.parse("2010-05-01")).should == 10
210
+ test.visits.set(5, Time.parse("2010-05-01"))
211
+ test.visits.add(5, Time.parse("2010-05-01"))
212
+ test.visits.on(Time.parse("2010-05-01")).should == 10
213
+ Test.find(object_id).visits.on(Time.parse("2010-05-01")).should == 10
221
214
  end
222
215
 
223
216
  it "on() accessor must work on dates as String" do
224
- # We have data for today as previous tests populated the visits field
225
- @mock.visits.on("2010-05-01").should == 10
217
+ test.visits.set(5, Time.parse("2010-05-01"))
218
+ test.visits.add(5, Time.parse("2010-05-01"))
219
+ test.visits.on("2010-05-01").should == 10
226
220
  end
227
221
 
228
222
  it "on() accessor must work on Date descendants" do
229
- # We have data for today as previous tests populated the visits field
230
- @mock.visits.on(Date.parse("2010-05-01")).should == 10
223
+ test.visits.set(5, Time.parse("2010-05-01"))
224
+ test.visits.add(5, Time.parse("2010-05-01"))
225
+ test.visits.on(Date.parse("2010-05-01")).should == 10
231
226
  end
232
227
 
233
228
  it "on() accessor must work on dates as Ranges" do
234
- # We have data for today as previous tests populated the visits field
235
- @mock.visits.on(Time.parse("2010-04-30")..Time.parse("2010-05-02")).should == [0, 10, 0]
229
+ test.visits.set(5, Time.parse("2010-05-01"))
230
+ test.visits.add(5, Time.parse("2010-05-01"))
231
+ test.visits.on(Time.parse("2010-04-30")..Time.parse("2010-05-02")).should == [0, 10, 0]
236
232
  end
237
233
  end
238
234
 
@@ -1,78 +1,25 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
1
+ # encoding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ require "trackoid/version"
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "trackoid"
8
- s.version = "0.3.8"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.version = Trackoid::VERSION
9
+ s.platform = Gem::Platform::RUBY
11
10
  s.authors = ["Jose Miguel Perez"]
12
- s.date = "2012-07-07"
13
- s.description = "Trackoid uses an embeddable approach to track analytics data using the poweful features of MongoDB for scalability"
14
11
  s.email = "josemiguel@perezruiz.com"
15
- s.extra_rdoc_files = [
16
- "LICENSE",
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- ".document",
21
- ".rspec",
22
- "Gemfile",
23
- "LICENSE",
24
- "README.rdoc",
25
- "Rakefile",
26
- "VERSION",
27
- "lib/trackoid.rb",
28
- "lib/trackoid/aggregates.rb",
29
- "lib/trackoid/core_ext.rb",
30
- "lib/trackoid/core_ext/range.rb",
31
- "lib/trackoid/core_ext/time.rb",
32
- "lib/trackoid/errors.rb",
33
- "lib/trackoid/reader_extender.rb",
34
- "lib/trackoid/readers.rb",
35
- "lib/trackoid/tracker.rb",
36
- "lib/trackoid/tracker_aggregates.rb",
37
- "lib/trackoid/tracking.rb",
38
- "spec/aggregates_spec.rb",
39
- "spec/ext/range_spec.rb",
40
- "spec/ext/time_spec.rb",
41
- "spec/reader_extender_spec.rb",
42
- "spec/readers_spec.rb",
43
- "spec/spec.opts",
44
- "spec/spec_helper.rb",
45
- "spec/timezone_spec.rb",
46
- "spec/trackoid_spec.rb",
47
- "trackoid.gemspec"
48
- ]
49
12
  s.homepage = "http://github.com/twoixter/trackoid"
50
- s.require_paths = ["lib"]
51
- s.rubygems_version = "1.8.24"
52
13
  s.summary = "Trackoid is an easy scalable analytics tracker using MongoDB and Mongoid"
14
+ s.description = "Trackoid uses an embeddable approach to track analytics data using the poweful features of MongoDB for scalability"
15
+ s.rubyforge_project = "trackoid"
16
+ s.require_paths = ["lib"]
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
53
20
 
54
- if s.respond_to? :specification_version then
55
- s.specification_version = 3
56
-
57
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
- s.add_runtime_dependency(%q<mongoid>, [">= 2.1.0"])
59
- s.add_development_dependency(%q<rake>, [">= 0"])
60
- s.add_development_dependency(%q<jeweler>, [">= 0"])
61
- s.add_development_dependency(%q<rspec>, [">= 2.2.0"])
62
- s.add_development_dependency(%q<mocha>, ["= 0.11.0"])
63
- else
64
- s.add_dependency(%q<mongoid>, [">= 2.1.0"])
65
- s.add_dependency(%q<rake>, [">= 0"])
66
- s.add_dependency(%q<jeweler>, [">= 0"])
67
- s.add_dependency(%q<rspec>, [">= 2.2.0"])
68
- s.add_dependency(%q<mocha>, ["= 0.11.0"])
69
- end
70
- else
71
- s.add_dependency(%q<mongoid>, [">= 2.1.0"])
72
- s.add_dependency(%q<rake>, [">= 0"])
73
- s.add_dependency(%q<jeweler>, [">= 0"])
74
- s.add_dependency(%q<rspec>, [">= 2.2.0"])
75
- s.add_dependency(%q<mocha>, ["= 0.11.0"])
76
- end
21
+ s.add_dependency 'mongoid', '~> 3.0.5'
22
+ s.add_dependency 'rake'
23
+ s.add_development_dependency 'rspec'
24
+ s.add_development_dependency 'mocha'
77
25
  end
78
-