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 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.5
1
+ 0.1.6
@@ -32,8 +32,8 @@ module Mongoid #:nodoc:
32
32
  end
33
33
 
34
34
  # Update methods
35
- def add(how_much = 1, date = DateTime.now)
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 = DateTime.now)
53
+ def inc(date = Date.today)
54
54
  add(1, date)
55
55
  end
56
56
 
57
- def dec(date = DateTime.now)
57
+ def dec(date = Date.today)
58
58
  add(-1, date)
59
59
  end
60
60
 
61
- def set(how_much, date = DateTime.now)
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 = DateTime.now, []
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
@@ -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
- context "testing accessor operations without reloading models" do
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.5"
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-15}
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: 17
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 5
10
- version: 0.1.5
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-15 00:00:00 +02:00
18
+ date: 2010-07-16 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency