duly_noted 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/DOCS.md CHANGED
@@ -21,10 +21,6 @@ The **DulyNoted** module contains five main methods:
21
21
 
22
22
  `meta_fields`: An array of fields to retrieve from the meta hash. If not specified, the entire hash will be grabbed. Fields will be converted to strings, because redis converts all hash keys and values to strings.
23
23
 
24
- `ref_id`: If you need to reference the metric later, perhaps to add more metadata later on, you can set a reference id that you can use to update the metric. The `ref_id` must be unique across `metric_name`s.
25
-
26
- `editable_for`: If you want to clear `ref_id`s out, you can set the metric to only be editable for a certain amount of time. `editable_for` is defined in seconds. After that amount of time, you will no longer be able to edit the meta data, and you may use that `ref_id` again. By default, `ref_id`s never expire.
27
-
28
24
  `time_start`: The start of the time range to grab the data from. **Important:** `time_start` should always be the time farthest in the past.
29
25
 
30
26
  `time_end`: The end of the time range to grab the data from. **Important:** `time_end` should always be the time closest to the present.
@@ -35,9 +31,11 @@ The **DulyNoted** module contains five main methods:
35
31
 
36
32
  ##Track
37
33
 
38
- _parameters: `metric_name`, `for`(optional), `generated_at`(optional), `meta`(optional), `ref_id`(optional), `editable_for`(optional)_
34
+ _parameters: `metric_name`, `for`(optional), `generated_at`(optional), `meta`(optional)_
35
+
36
+ _returns: `id` for editing metadata_
39
37
 
40
- Use track to track an event, like a page view, or a download. Use the `for` option to give an event a context. For instance, for page views, you might set `for` to `home_page`, so that you know which page was viewed. You can also store metadata along with your metric with the `meta` hash. If you need to update that `meta` hash at a later time, you can set a `ref_id`, which can be used to tell `#update` exactly which metric you want to update. `ref_id`s have to be unique across `metric_name`s, and if you want to free up your `ref_id`s, you can set them to expire after a certain number of seconds with `editable_for`.
38
+ Use track to track an event, like a page view, or a download. Use the `for` option to give an event a context. For instance, for page views, you might set `for` to `home_page`, so that you know which page was viewed. You can also store metadata along with your metric with the `meta` hash.
41
39
 
42
40
  ###Usage
43
41
 
@@ -45,21 +43,21 @@ Use track to track an event, like a page view, or a download. Use the `for` opt
45
43
 
46
44
  DulyNoted.track("video_plays", for: ["user_7261", "video_917216"], meta: {amount_watched: 0})
47
45
 
48
- DulyNoted.track("purchases", for: "user_281", generated_at: 1.day.ago, ref_id: "pid_28172", editable_for: 30)
46
+ DulyNoted.track("purchases", for: "user_281", generated_at: 1.day.ago)
49
47
 
50
48
 
51
49
 
52
50
  ##Update
53
51
 
54
- _parameters: `metric_name`, `ref_id`, `meta`(optional), `editable_for`(optional)_
52
+ _parameters: `id`, `meta`(optional)_
55
53
 
56
- Use update to add, or edit the metadata stored with a metric. You can optionally set the `editable_for` option which will override any setting set by track. So if it was set to expire in 30 seconds, and in 20 seconds you called update with `editable_for` set to `30`, it would be editable for 30 seconds from the moment you updated it.
54
+ Use update to add, or edit the metadata stored with a metric.
57
55
 
58
56
  ###Usage
59
57
 
60
- DulyNoted.track("page_views", ref_id: "a_unique_id", meta: {time_on_page: 0, browser: "chrome"})
58
+ DulyNoted.track("page_views", meta: {time_on_page: 0, browser: "chrome"}) # => 5673
61
59
 
62
- DulyNoted.update("page_views", "a_unique_id", meta: { time_on_page: 30 }, editable_for: 30)
60
+ DulyNoted.update(5673, meta: { time_on_page: 30 })
63
61
 
64
62
 
65
63
 
data/README.md CHANGED
@@ -1,5 +1,3 @@
1
- _Currently being updated for v1.0.0..._
2
-
3
1
  #Duly Noted
4
2
  [![Build Status](https://secure.travis-ci.org/willcosgrove/duly_noted.png?branch=master)](http://travis-ci.org/willcosgrove/duly_noted)
5
3
 
@@ -10,6 +8,10 @@ Duly noted is a redis backed stats and metrics tracker. It works as follows:
10
8
  This would log one page view for the home page. Then to see how many page views the home page has gotten, you would simply call:
11
9
 
12
10
  DulyNoted.count("page_views", for: "homepage")
11
+
12
+ To count how many page views there have been across all pages, you can call:
13
+
14
+ DulyNoted.count("page_views")
13
15
 
14
16
  You can also store meta data with your metrics by passing your data in a hash to the `meta` key like so:
15
17
 
@@ -29,6 +31,8 @@ You can also just specify a `time_range` like so:
29
31
 
30
32
  This will return the page view count for the home page for the past day.
31
33
 
34
+ There are a few other things it can do, check out the [docs]("http://willcosgrove.github.com/duly_noted") for more info.
35
+
32
36
  ##Install
33
37
 
34
38
  You probably already guessed it, but to install just
@@ -43,24 +47,39 @@ to your `gemfile` and run `bundle install`
43
47
 
44
48
  ##What's New
45
49
 
50
+ ### 1.0.1
51
+ * Obliterated `ref_id`s, and everything they stood for. Not really everything they stood for. Now each metric gets its own unique id.
52
+ * `#track` now returns the id of the metric you just tracked
53
+ * id's are unique across all of duly_noted, so when you update them with `#update` you don't need to specify which metric_name
54
+ * The first time you run a duly_noted command after updating the gem, it will attempt to update your redis schema. I did this on my own duly_noted setup with about 110k worth of unique metrics tracked, a DB size of 19MB, and a key count of 6 to a DB size of 35MB and a key count of 110600 in 75.26 seconds. In the next version, I'm either going to move the id keys into a hash, so it doesn't pollute the global keyspace any more than it has to, or, I'm going to set a default expire time on each id reference key. I'm leaning towards the expiration idea, because I don't think people have a use for being able to update any metric entry at any time.
55
+
56
+ ### 1.0.0
57
+ * `for` is no longer required on `count` and `query`. If you call one of them without `for` it will count all of whatever metric you specified
58
+ * Added the `chart` method, which allows you to pull out your data in a handy way that's perfect for giving it to a charting library
59
+ * Now pipelines all of the keys that are set in the `track` method
60
+ * Added errors so that you know when something's gone wrong!
61
+ * Added the Updater which will do redis schema upgrades automatically when duly_noted does another major upgrade
62
+ * A special `count_x_by_y` dynamic method. Say you've tracked page views, and in the meta hash, you've stored their browser name. Now you want a breakdown of page views by browser, well… `DulyNoted.count_page_views_by_browser` would do just that. Yay metaprogramming!
63
+ * Added the ability to expire `ref_id`s. So if you know that you'll only need to edit your metadata for, say, the next 10 minutes, you can set the `editable_for` options to `10.minutes` in the `track`, or in the `update` method. By default, `ref_id`s never expire.
64
+ * Some other little behind the scenes methods to help for the big surprise in 1.5.0
65
+
46
66
  ### 0.1.0
47
67
 
48
68
  * Added the `time_range` option to `count`, and `query`
49
69
 
50
70
  * Added the `meta_fields` option to `query`, which takes an array of fields to pull out from the meta hash
51
71
 
52
- * Added the `ref_id` option to `query`, which takes a reference id and will return an array with one meta hash. I was going back and forth on whether or not it should wrap the hash in an array. It doesn't need to be, but I thought, just to make it consistant with it's usual output, I should make it return an array.
72
+ * Added the `ref_id` option to `query`, which takes a reference id and will return an array with one meta hash. I was going back and forth on whether or not it should wrap the hash in an array. It doesn't need to be, but I thought, just to make it consistent with it's usual output, I should make it return an array.
53
73
 
54
74
  * Enough bug fixes to make it production ready! Yay!
55
75
 
56
76
 
57
- ##To Do
58
-
59
- * Count by meta fields: How many page views from each browser?
77
+ ##What's Gonna Be New
60
78
 
61
- * A `chart` method which would take a `time_start`, `time_end`, and a `granularity` which would allow you to easily get the per hour for each hour for the past day, for example.
79
+ ###1.5.0
80
+ * A sinatra app to view and peruse your metrics (think, resque)
81
+ * Resolution decay: currently, duly_noted stores all metrics at the highest resolution, timestamped down to a fraction of a second. With resolution decay, you can specify fall offs so that after, say, a month, they'll be grouped by day. So after a month has passed, you couldn't go back to a day and see it by hour, only total for that day. This will tremendously cut back on space, and is, of course, totally customizable.
62
82
 
63
- * Maybe some Rails view helpers to generate some code for a Javascript charting library, or Google Charts API.
64
83
 
65
84
  ##Contributing
66
85
  If you want to help, you should do it. Fork it, fix it, and send me a pull request. I will be delighted.
@@ -72,10 +72,6 @@ module DulyNoted
72
72
  #
73
73
  # `meta_fields`: An array of fields to retrieve from the meta hash. If not specified, the entire hash will be grabbed. Fields will be converted to strings, because redis converts all hash keys and values to strings.
74
74
  #
75
- # `ref_id`: If you need to reference the metric later, perhaps to add more metadata later on, you can set a reference id that you can use to update the metric. The `ref_id` must be unique across `metric_name`s.
76
- #
77
- # `editable_for`: If you want to clear `ref_id`s out, you can set the metric to only be editable for a certain amount of time. `editable_for` is defined in seconds. After that amount of time, you will no longer be able to edit the meta data, and you may use that `ref_id` again. By default, `ref_id`s never expire.
78
- #
79
75
  # `time_start`: The start of the time range to grab the data from. **Important:** `time_start` should always be the time farthest in the past.
80
76
  #
81
77
  # `time_end`: The end of the time range to grab the data from. **Important:** `time_end` should always be the time closest to the present.
@@ -84,16 +80,14 @@ module DulyNoted
84
80
 
85
81
  # ##Track
86
82
 
87
- # _parameters: `metric_name`, `for`(optional), `generated_at`(optional), `meta`(optional), `ref_id`(optional), `editable_for`(optional)_
88
-
83
+ # _parameters: `metric_name`, `for`(optional), `generated_at`(optional), `meta`(optional)_
84
+ #
85
+ # _returns: `id` for editing metadata_
86
+ #
89
87
  # Use track to track an event, like a page view, or a download. Use the `for` option
90
88
  # to give an event a context. For instance, for page views, you might set `for` to
91
89
  # `home_page`, so that you know which page was viewed. You can also store metadata
92
- # along with your metric with the `meta` hash. If you need to update that `meta` hash
93
- # at a later time, you can set a `ref_id`, which can be used to tell `#update`
94
- # exactly which metric you want to update. `ref_id`s have to be unique across
95
- # `metric_name`s, and if you want to free up your `ref_id`s, you can set them to expire
96
- # after a certain number of seconds with `editable_for`.
90
+ # along with your metric with the `meta` hash.
97
91
  #
98
92
  # ###Usage
99
93
 
@@ -107,49 +101,45 @@ module DulyNoted
107
101
  #
108
102
  # DulyNoted.track("purchases",
109
103
  # for: "user_281",
110
- # generated_at: 1.day.ago,
111
- # ref_id: "pid_28172",
112
- # editable_for: 30)
104
+ # generated_at: 1.day.ago)
113
105
 
114
106
  def track(metric_name, options={})
115
107
  options = {:generated_at => Time.now}.merge(options)
116
108
  key = build_key(metric_name)
109
+ key_without_for = key.dup
110
+ id = DulyNoted.redis.incr "dnid"
117
111
  key << assemble_for(options)
118
112
  DulyNoted.redis.pipelined do
119
- DulyNoted.redis.sadd build_key("metrics"), build_key(metric_name)
120
- DulyNoted.redis.zadd key, options[:generated_at].to_f, "#{key}:#{options[:generated_at].to_f}:meta"
121
- DulyNoted.redis.set "#{build_key(metric_name)}:ref:#{options[:ref_id]}", "#{key}:#{options[:generated_at].to_f}:meta" if options[:ref_id] # set alias key
122
- DulyNoted.redis.expire "#{build_key(metric_name)}:ref:#{options[:ref_id]}", options[:editable_for] if options[:editable_for]
113
+ DulyNoted.redis.sadd build_key("metrics", false), key_without_for
114
+ DulyNoted.redis.zadd key, options[:generated_at].to_f, "#{key}:#{id}:meta"
115
+ DulyNoted.redis.set "dnid:#{id}", "#{key}:#{id}:meta" # set alias key
123
116
  if options[:meta] # set meta data
124
- DulyNoted.redis.mapped_hmset "#{key}:#{options[:generated_at].to_f}:meta", options[:meta]
117
+ DulyNoted.redis.mapped_hmset "#{key}:#{id}:meta", options[:meta]
125
118
  options[:meta].keys.each do |field|
126
119
  DulyNoted.redis.sadd "#{key}:fields", field
127
120
  end
128
121
  end
129
122
  end
123
+ id
130
124
  end
131
125
 
132
126
  # ##Update
133
127
  #
134
- # _parameters: `metric_name`, `ref_id`, `meta`(optional), `editable_for`(optional)_
128
+ # _parameters: `id`, `meta`(optional)_
135
129
  #
136
- # Use update to add, or edit the metadata stored with a metric. You can optionally set the `editable_for` option which will override any setting set by track. So if it was set to expire in 30 seconds, and in 20 seconds you called update with `editable_for` set to `30`, it would be editable for 30 seconds from the moment you updated it.
130
+ # Use update to add, or edit the metadata stored with a metric.
137
131
  #
138
132
  # ###Usage
139
133
  #
140
134
  # DulyNoted.track("page_views",
141
- # ref_id: "a_unique_id",
142
- # meta: {time_on_page: 0, browser: "chrome"})
143
- # DulyNoted.update("page_views",
144
- # "a_unique_id",
145
- # meta: { time_on_page: 30 },
146
- # editable_for: 30)
135
+ # meta: {time_on_page: 0, browser: "chrome"}) # => 5673
136
+ # DulyNoted.update(5673,
137
+ # meta: { time_on_page: 30 })
147
138
 
148
- def update(metric_name, ref_id, options={})
149
- key = build_key(metric_name)
150
- key << ":ref:#{ref_id}"
139
+ def update(id, options={})
140
+ key = "dnid:#{id}"
151
141
  real_key = DulyNoted.redis.get key
152
- raise InvalidRefId if real_key == nil
142
+ raise InvalidId if real_key == nil
153
143
  DulyNoted.redis.mapped_hmset real_key, options[:meta] if options[:meta]
154
144
  end
155
145
 
@@ -171,8 +161,8 @@ module DulyNoted
171
161
  key = build_key(metric_name)
172
162
  parse_time_range(options)
173
163
  key << assemble_for(options)
174
- if options[:ref_id]
175
- key << ":ref:#{options[:ref_id]}"
164
+ if options[:id]
165
+ key = "dnid:#{options[:id]}"
176
166
  real_key = DulyNoted.redis.get key
177
167
  if options[:meta_fields]
178
168
  options[:meta_fields].collect! { |x| x.to_s }
@@ -382,6 +372,6 @@ module DulyNoted
382
372
  class NotValidMetric < StandardError; end
383
373
  class InvalidOptions < StandardError; end
384
374
  class InvalidStep < StandardError; end
385
- class InvalidRefId < StandardError; end
375
+ class InvalidId < StandardError; end
386
376
  class UpdateError < StandardError; end
387
377
  end
@@ -23,12 +23,13 @@ module DulyNoted
23
23
  end
24
24
  end
25
25
 
26
- def find_keys(key)
26
+ def find_keys(key, redis=nil)
27
+ redis ||= DulyNoted.redis
27
28
  keys = []
28
- keys += DulyNoted.redis.keys("#{key}*")
29
- keys -= DulyNoted.redis.keys("#{key}:*:meta")
30
- keys -= DulyNoted.redis.keys("#{key}:ref:*")
31
- keys -= DulyNoted.redis.keys("#{key}*fields")
29
+ keys += redis.keys("#{key}*")
30
+ keys -= redis.keys("#{key}:*:meta")
31
+ keys -= redis.keys("#{key}:ref:*")
32
+ keys -= redis.keys("#{key}*fields")
32
33
  end
33
34
 
34
35
  def parse_time_range(options)
@@ -1,11 +1,37 @@
1
1
  require "duly_noted/version"
2
+ require "duly_noted/helpers"
2
3
 
3
4
  module DulyNoted
4
5
  module Updater
5
6
  def update_schema(schema_version, redis)
6
- # magic updating!
7
+ time = Time.now
8
+ if schema_version = [1,0,0]
9
+ #update to 1.0.1
10
+ puts "Updating schema to comply with duly_noted 1.0.1"
11
+ metrics = redis.smembers "dn:metrics"
12
+ metrics.each do |metric|
13
+ keys = find_keys(metric, redis)
14
+ keys.each do |key|
15
+ events = redis.zrange key, 0, -1
16
+ events.each do |event|
17
+ id = redis.incr "dnid"
18
+ redis.zadd(key, redis.zscore(key, event), event.gsub(/:\d{10}.\d+:/, ":#{id}:"))
19
+ redis.set("dnid:#{id}", "#{key}:#{id}:meta")
20
+ if(redis.exists(event))
21
+ redis.mapped_hmset "#{key}:#{id}:meta", redis.hgetall(event)
22
+ redis.del(event)
23
+ end
24
+ redis.zrem(key, event)
25
+ end
26
+ end
27
+ end
28
+ redis.keys("*:ref:*").each do |ref_keys|
29
+ redis.del(ref_keys)
30
+ end
31
+ schema_version = [1,0,1]
32
+ end
7
33
  redis.set "dn:version", VERSION
8
- puts "All up to date"
34
+ puts "All up to date. Completed updates in #{Time.now-time} seconds."
9
35
  return true
10
36
  end
11
37
 
@@ -14,9 +40,8 @@ module DulyNoted
14
40
  if !schema_version.nil?
15
41
  schema_version = schema_version.split(".")
16
42
  current_version = VERSION.split(".")
17
- if schema_version[0] != current_version[0]
18
- puts "Your duly_noted schema needs to be updated"
19
- if update_schema(schema_version.join("."), redis)
43
+ if schema_version != current_version
44
+ if update_schema(schema_version, redis)
20
45
  check_schema(redis)
21
46
  else
22
47
  raise UpdateError
@@ -1,3 +1,3 @@
1
1
  module DulyNoted
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe DulyNoted do
4
4
  before :each do
5
- DulyNoted.redis.flushall
5
+ DulyNoted.redis.flushdb
6
6
  Timecop.return
7
7
  end
8
8
 
@@ -32,27 +32,23 @@ describe DulyNoted do
32
32
  DulyNoted.track "page_views", :generated_at => Time.now-10
33
33
  DulyNoted.count "page_views", :time_range => Time.now-11..Time.now-9
34
34
  end
35
- it "will allow you to set expirations on `ref_id`s" do
36
- DulyNoted.track "page_views", :meta => {:open => true}, :ref_id => "unique", :editable_for => 0
37
- expect { DulyNoted.update("page_views", "unique") }.to raise_error(DulyNoted::InvalidRefId)
38
- end
39
35
  end
40
36
 
41
37
  describe "#update" do
42
38
  it "overwrites duplicate keys" do
43
- DulyNoted.track "page_views", :meta => {:seconds_open => 0}, :ref_id => "unique"
44
- DulyNoted.update "page_views", "unique", :meta => {:seconds_open => 5}
39
+ id = DulyNoted.track "page_views", :meta => {:seconds_open => 0}
40
+ DulyNoted.update id, :meta => {:seconds_open => 5}
45
41
  DulyNoted.query("page_views").should include({"seconds_open" => "5"})
46
42
  DulyNoted.query("page_views").should_not include({"seconds_open" => "0"})
47
43
  end
48
44
  it "doesn't replace old hash" do
49
- DulyNoted.track "page_views", :meta => {:seconds_open => 0}, :ref_id => "unique"
50
- DulyNoted.update "page_views", "unique", :meta => {:ip_address => "19.27.182.32"}
45
+ id = DulyNoted.track "page_views", :meta => {:seconds_open => 0}
46
+ DulyNoted.update id, :meta => {:ip_address => "19.27.182.32"}
51
47
  DulyNoted.query("page_views").should include({"seconds_open" => "0", "ip_address" => "19.27.182.32"})
52
48
  end
53
49
  it "does not require that `for:` be set to update" do
54
- DulyNoted.track "page_views", :for => "home", :meta => {:seconds_open => 0}, :ref_id => "unique"
55
- DulyNoted.update "page_views", "unique", :meta => {:seconds_open => 5}
50
+ id = DulyNoted.track "page_views", :for => "home", :meta => {:seconds_open => 0}
51
+ DulyNoted.update id, :meta => {:seconds_open => 5}
56
52
  DulyNoted.query("page_views").should include({"seconds_open" => "5"})
57
53
  end
58
54
  end
@@ -62,11 +58,11 @@ describe DulyNoted do
62
58
  DulyNoted.track "page_views", :meta => {:seconds_open => 0, :browser => "chrome"}
63
59
  DulyNoted.query("page_views").should include({"seconds_open" => "0", "browser" => "chrome"})
64
60
  end
65
- it "can query a certain ref_id" do
66
- DulyNoted.track "page_views", :meta => {:seconds_open => 0, :browser => "chrome"}, :ref_id => "unique"
61
+ it "can query a certain id" do
62
+ id = DulyNoted.track "page_views", :meta => {:seconds_open => 0, :browser => "chrome"}
67
63
  DulyNoted.track "page_views", :meta => {:seconds_open => 10, :browser => "firefox"}
68
- DulyNoted.query("page_views", :ref_id => "unique").should include({"seconds_open" => "0", "browser" => "chrome"})
69
- DulyNoted.query("page_views", :ref_id => "unique").should_not include({"seconds_open" => "10", "browser" => "firefox"})
64
+ DulyNoted.query("page_views", :id => id).should include({"seconds_open" => "0", "browser" => "chrome"})
65
+ DulyNoted.query("page_views", :id => id).should_not include({"seconds_open" => "10", "browser" => "firefox"})
70
66
  end
71
67
  it "can grab only specific fields from the hash" do
72
68
  DulyNoted.track "page_views", :meta => {:seconds_open => 0, :browser => "chrome"}
@@ -123,19 +119,19 @@ describe DulyNoted do
123
119
  DulyNoted.chart("page_views", :time_range => Time.now-(3)..Time.now-(1), :step => (1)).should eq({(Time.now-3).to_i => 1, (Time.now-2).to_i => 2, (Time.now-1).to_i => 3})
124
120
  end
125
121
  it "can count events between a time range, without a step set" do
126
- DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 12:30am")
127
- DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 1:20am")
128
- DulyNoted.chart("page_views", :time_range => Chronic.parse("yesterday at 12am")...Chronic.parse("yesterday at 2am"), :data_points => 2).should eq({Chronic.parse("yesterday at 12am").to_i => 1, Chronic.parse("yesterday at 1am").to_i => 1})
122
+ DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 12:30pm")
123
+ DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 1:20pm")
124
+ DulyNoted.chart("page_views", :time_range => Chronic.parse("yesterday at 12pm")...Chronic.parse("yesterday at 2pm"), :data_points => 2).should eq({Chronic.parse("yesterday at 12pm").to_i => 1, Chronic.parse("yesterday at 1pm").to_i => 1})
129
125
  end
130
126
  it "will take time_start, step, and data_points options to build a chart" do
131
- DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 12:30am")
132
- DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 1:20am")
133
- DulyNoted.chart("page_views", :time_start => Chronic.parse("yesterday at 12am"), :step => (3600), :data_points => 2).should eq({Chronic.parse("yesterday at 12am").to_i => 1, Chronic.parse("yesterday at 1am").to_i => 1})
127
+ DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 12:30pm")
128
+ DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 1:20pm")
129
+ DulyNoted.chart("page_views", :time_start => Chronic.parse("yesterday at 12pm"), :step => (3600), :data_points => 2).should eq({Chronic.parse("yesterday at 12pm").to_i => 1, Chronic.parse("yesterday at 1pm").to_i => 1})
134
130
  end
135
131
  it "will take time_end, step, and data_points options to build a chart" do
136
- DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 12:30am")
137
- DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 1:20am")
138
- DulyNoted.chart("page_views", :time_end => Chronic.parse("yesterday at 2am"), :step => (3600), :data_points => 2).should eq({Chronic.parse("yesterday at 2am").to_i => 1, Chronic.parse("yesterday at 1am").to_i => 1})
132
+ DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 12:30pm")
133
+ DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 1:20pm")
134
+ DulyNoted.chart("page_views", :time_end => Chronic.parse("yesterday at 2pm"), :step => (3600), :data_points => 2).should eq({Chronic.parse("yesterday at 2pm").to_i => 1, Chronic.parse("yesterday at 1pm").to_i => 1})
139
135
  end
140
136
  it "should raise InvalidStep if you give it a step of zero" do
141
137
  DulyNoted.track "page_views"
@@ -146,9 +142,9 @@ describe DulyNoted do
146
142
  expect { DulyNoted.chart("page_views", :time_end => Time.now, :step => 60*60) }.to raise_error(DulyNoted::InvalidOptions)
147
143
  end
148
144
  it "should chart everything if no time range is specified" do
149
- DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 12:30am")
150
- DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 1:20am")
151
- DulyNoted.chart("page_views", :data_points => 2).should eq({Chronic.parse("yesterday at 12:30am").to_i => 1, Chronic.parse("yesterday at 12:55am").to_i => 1})
145
+ DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 12:30pm")
146
+ DulyNoted.track "page_views", :generated_at => Chronic.parse("yesterday at 1:20pm")
147
+ DulyNoted.chart("page_views", :data_points => 2).should eq({Chronic.parse("yesterday at 12:30pm").to_i => 1, Chronic.parse("yesterday at 12:55pm").to_i => 1})
152
148
  end
153
149
  end
154
150
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duly_noted
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-08 00:00:00.000000000 Z
12
+ date: 2012-03-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
16
- requirement: &70176012443720 !ruby/object:Gem::Requirement
16
+ requirement: &70148931411020 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70176012443720
24
+ version_requirements: *70148931411020
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70176012459660 !ruby/object:Gem::Requirement
27
+ requirement: &70148931410600 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70176012459660
35
+ version_requirements: *70148931410600
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &70176012459240 !ruby/object:Gem::Requirement
38
+ requirement: &70148931410180 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70176012459240
46
+ version_requirements: *70148931410180
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rb-fsevent
49
- requirement: &70176012458820 !ruby/object:Gem::Requirement
49
+ requirement: &70148931409760 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70176012458820
57
+ version_requirements: *70148931409760
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: guard-rspec
60
- requirement: &70176012458400 !ruby/object:Gem::Requirement
60
+ requirement: &70148931409340 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70176012458400
68
+ version_requirements: *70148931409340
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: guard-bundler
71
- requirement: &70176012457980 !ruby/object:Gem::Requirement
71
+ requirement: &70148931408920 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70176012457980
79
+ version_requirements: *70148931408920
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: chronic
82
- requirement: &70176012457560 !ruby/object:Gem::Requirement
82
+ requirement: &70148931408500 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70176012457560
90
+ version_requirements: *70148931408500
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: timecop
93
- requirement: &70176012457140 !ruby/object:Gem::Requirement
93
+ requirement: &70148931424440 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70176012457140
101
+ version_requirements: *70148931424440
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: ruby_gntp
104
- requirement: &70176012456720 !ruby/object:Gem::Requirement
104
+ requirement: &70148931424020 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70176012456720
112
+ version_requirements: *70148931424020
113
113
  description: a simple redis based stat-tracker
114
114
  email:
115
115
  - will@willcosgrove.com
@@ -146,7 +146,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
146
146
  version: '0'
147
147
  segments:
148
148
  - 0
149
- hash: 2593334725054151131
149
+ hash: -502772928455294375
150
150
  required_rubygems_version: !ruby/object:Gem::Requirement
151
151
  none: false
152
152
  requirements:
@@ -155,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
155
  version: '0'
156
156
  segments:
157
157
  - 0
158
- hash: 2593334725054151131
158
+ hash: -502772928455294375
159
159
  requirements: []
160
160
  rubyforge_project:
161
161
  rubygems_version: 1.8.16