timemaster 0.1.0
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/.document +5 -0
- data/.gitignore +2 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +69 -0
- data/TODO +26 -0
- data/VERSION +1 -0
- data/examples/request.rb +42 -0
- data/lib/timemaster.rb +22 -0
- data/lib/timemaster/document.rb +158 -0
- data/lib/timemaster/extensions.rb +84 -0
- data/lib/timemaster/helpers.rb +29 -0
- data/lib/timemaster/resolution.rb +62 -0
- data/lib/timemaster/version.rb +5 -0
- data/test/chronos_test.rb +12 -0
- data/test/teststrap.rb +30 -0
- metadata +141 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 brianthecoder
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
= Timemaster
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
13
|
+
* Send me a pull request. Bonus points for topic branches.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2010 brianthecoder. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "timemaster"
|
8
|
+
gem.summary = %Q{A way to easily store time based data scalably in riak}
|
9
|
+
gem.description = %Q{Creates buckets for a given resolution and will create all the appropriate links}
|
10
|
+
gem.email = "wbsmith83@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/BrianTheCoder/chronos"
|
12
|
+
gem.authors = ["brianthecoder"]
|
13
|
+
gem.files.include %w(lib/timemaster.rb lib/timemaster/document.rb lib/timemaster/extensions.rb lib/timemaster/helpers.rb lib/timemaster/resolution.rb lib/timemaster/version.rb)
|
14
|
+
gem.add_development_dependency "yard"
|
15
|
+
gem.add_dependency "riak-client"
|
16
|
+
gem.add_dependency "activesupport"
|
17
|
+
gem.add_dependency "hashie"
|
18
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
|
+
end
|
20
|
+
Jeweler::GemcutterTasks.new
|
21
|
+
rescue LoadError
|
22
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'rake/testtask'
|
26
|
+
Rake::TestTask.new(:test) do |test|
|
27
|
+
test.libs << 'lib' << 'test'
|
28
|
+
test.pattern = 'test/**/*_test.rb'
|
29
|
+
test.verbose = true
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
require 'rcov/rcovtask'
|
34
|
+
Rcov::RcovTask.new do |test|
|
35
|
+
test.libs << 'test'
|
36
|
+
test.pattern = 'test/**/*_test.rb'
|
37
|
+
test.verbose = true
|
38
|
+
end
|
39
|
+
rescue LoadError
|
40
|
+
task :rcov do
|
41
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
task :test => :check_dependencies
|
46
|
+
|
47
|
+
begin
|
48
|
+
require 'reek/rake_task'
|
49
|
+
Reek::RakeTask.new do |t|
|
50
|
+
t.fail_on_error = true
|
51
|
+
t.verbose = false
|
52
|
+
t.source_files = 'lib/**/*.rb'
|
53
|
+
end
|
54
|
+
rescue LoadError
|
55
|
+
task :reek do
|
56
|
+
abort "Reek is not available. In order to run reek, you must: sudo gem install reek"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
task :default => :test
|
61
|
+
|
62
|
+
begin
|
63
|
+
require 'yard'
|
64
|
+
YARD::Rake::YardocTask.new
|
65
|
+
rescue LoadError
|
66
|
+
task :yardoc do
|
67
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
68
|
+
end
|
69
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
class Request
|
2
|
+
include Chronos::Document
|
3
|
+
|
4
|
+
# default, assumes all levels above it
|
5
|
+
resolution :minute
|
6
|
+
|
7
|
+
# generates automatically if not defined
|
8
|
+
def key
|
9
|
+
# blarg
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
* saving documents
|
14
|
+
* check that lined docs exist
|
15
|
+
* resolution content_type?
|
16
|
+
* queurying
|
17
|
+
* single doc
|
18
|
+
* epoch
|
19
|
+
* range
|
20
|
+
* stats (map/reduce)
|
21
|
+
* counts
|
22
|
+
* sum
|
23
|
+
* avg
|
24
|
+
|
25
|
+
* easy custom links
|
26
|
+
* query by custom links
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/examples/request.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'../lib/chronos')
|
2
|
+
|
3
|
+
require 'timecop'
|
4
|
+
require 'randexp'
|
5
|
+
|
6
|
+
Chronos.riak.port = 8091
|
7
|
+
|
8
|
+
class Request
|
9
|
+
include Chronos::Document
|
10
|
+
|
11
|
+
resolution :minute
|
12
|
+
|
13
|
+
tag :controller_name
|
14
|
+
tag :action_name
|
15
|
+
end
|
16
|
+
|
17
|
+
module Riak
|
18
|
+
class Bucket
|
19
|
+
def wipe!
|
20
|
+
keys do |key_array|
|
21
|
+
key_array.each{|key| delete(key)}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def wipe_all!
|
28
|
+
%w(years months days hours minutes requests).each{|name| Chronos.riak.bucket(name).wipe! }
|
29
|
+
end
|
30
|
+
|
31
|
+
def seed
|
32
|
+
controllers = %w(users posts settings photos)
|
33
|
+
actions = %w(index new create edit update destroy)
|
34
|
+
|
35
|
+
Timecop.freeze(Time.now)
|
36
|
+
200.of do
|
37
|
+
Timecop.travel(rand(10))
|
38
|
+
req = Request.new(:controller_name => controllers.pick,
|
39
|
+
:action_name => actions.pick,
|
40
|
+
:response_time => 5.of{ 60 + rand(40)}.sum)
|
41
|
+
end
|
42
|
+
end
|
data/lib/timemaster.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
require 'riak/client'
|
3
|
+
require 'hashie'
|
4
|
+
|
5
|
+
$:.unshift File.dirname(__FILE__)
|
6
|
+
|
7
|
+
require 'timemaster/helpers'
|
8
|
+
require 'timemaster/extensions'
|
9
|
+
require 'timemaster/document'
|
10
|
+
require 'timemaster/resolution'
|
11
|
+
|
12
|
+
module Timemaster
|
13
|
+
extend self
|
14
|
+
|
15
|
+
def riak
|
16
|
+
@riak ||= Riak::Client.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def riak=(client)
|
20
|
+
@riak ||= Riak::Client.new
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
module Timemaster
|
2
|
+
module Document
|
3
|
+
def self.included(klass)
|
4
|
+
klass.extend ClassMethods
|
5
|
+
klass.extend Helpers
|
6
|
+
klass.send(:include, Helpers)
|
7
|
+
klass.send(:attr_accessor, *[:key, :attributes])
|
8
|
+
klass.send(:attr_reader, :time)
|
9
|
+
klass.cattr_accessor :resolution_period
|
10
|
+
klass.cattr_accessor :tags
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def get(id)
|
15
|
+
begin
|
16
|
+
new bucket.get(id)
|
17
|
+
rescue Riak::FailedRequest
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def bucket_name
|
23
|
+
@bucket_name ||= self.to_s.tableize
|
24
|
+
end
|
25
|
+
|
26
|
+
def resolution(period)
|
27
|
+
self.resolution_period = period
|
28
|
+
end
|
29
|
+
|
30
|
+
def epoch(period = :hour, time = Time.now.utc, tag = nil)
|
31
|
+
# res_instance = Resolution.new(options[:resolution], options[:time])
|
32
|
+
index = Resolution.index(resolution_period)
|
33
|
+
res_index = Resolution.index(period)
|
34
|
+
resolutions = []
|
35
|
+
RESOLUTIONS[0..index].each_with_index do |res_period, i|
|
36
|
+
resolutions[i] = Resolution.new(res_period, (i <= res_index) ? time : nil)
|
37
|
+
end
|
38
|
+
root = resolutions.shift.riak_object
|
39
|
+
root.walk(resolutions.map(&:walk_spec).insert(-1, Riak::WalkSpec.new('requests', tag, true))).flatten
|
40
|
+
end
|
41
|
+
|
42
|
+
def period(resolution = :hour, start = 1.day.ago, stop = Time.now)
|
43
|
+
res_instance = Resolution.new(:hour)
|
44
|
+
keys = (start..stop).send(:"to_#{res_instance.bucket_name}")
|
45
|
+
keys.map! do |time|
|
46
|
+
res_instance.time = time
|
47
|
+
res_instance.key
|
48
|
+
end
|
49
|
+
keys
|
50
|
+
end
|
51
|
+
|
52
|
+
def tag(new_tag, options = {})
|
53
|
+
self.tags ||= []
|
54
|
+
self.tags << new_tag
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize(params = {})
|
59
|
+
case params
|
60
|
+
when Hash
|
61
|
+
@time = params.delete(:time) || Time.now.utc
|
62
|
+
@attributes = Hashie::Mash.new(params)
|
63
|
+
when Riak::RObject
|
64
|
+
self.riak_object = params
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def make_links
|
69
|
+
return link_for if self.class.tags.blank?
|
70
|
+
self.class.tags.map{|key| link_for("#{key}_#{@attributes[key.to_sym]}")}.flatten.compact
|
71
|
+
end
|
72
|
+
|
73
|
+
def time_from_link(link)
|
74
|
+
Time.utc(*link.url.split('/').last.split('_'))
|
75
|
+
end
|
76
|
+
|
77
|
+
def resolutions
|
78
|
+
@resolutions ||= RESOLUTIONS[0..resolution_index].inject({}) do |hash, period|
|
79
|
+
hash[period] = Resolution.new(period, time)
|
80
|
+
hash
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def resolution_index
|
85
|
+
@resolution_index ||= RESOLUTIONS.index(self.class.resolution_period)
|
86
|
+
end
|
87
|
+
|
88
|
+
def time=(timestamp)
|
89
|
+
case timestamp
|
90
|
+
when Date
|
91
|
+
self.time = timestamp.to_time
|
92
|
+
when Time
|
93
|
+
@time = timestamp.utc
|
94
|
+
when Riak::Link
|
95
|
+
self.time = time_from_link(timestamp)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def [](key)
|
100
|
+
@attributes[key]
|
101
|
+
end
|
102
|
+
|
103
|
+
def []=(key, value)
|
104
|
+
@attributes[key] = value
|
105
|
+
end
|
106
|
+
|
107
|
+
def method_missing(method_symbol, *args)
|
108
|
+
method_name = method_symbol.to_s
|
109
|
+
if %w(? =).include?(method_name[-1,1])
|
110
|
+
method = method_name[0..-2]
|
111
|
+
operator = method_name[-1,1]
|
112
|
+
if operator == '='
|
113
|
+
set_value(method, args.first)
|
114
|
+
elsif operator == '?'
|
115
|
+
!@attributes[method].blank?
|
116
|
+
end
|
117
|
+
else
|
118
|
+
@attributes[method_name]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def set_value(method, val)
|
123
|
+
if val.blank?
|
124
|
+
@attributes.delete(method)
|
125
|
+
else
|
126
|
+
@attributes[method] = val
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def bucket_name
|
131
|
+
@bucket_name ||= self.class.bucket_name
|
132
|
+
end
|
133
|
+
|
134
|
+
def resolution_docs
|
135
|
+
RESOLUTIONS[0..resolution_index].each do |period|
|
136
|
+
res_period = resolutions[period]
|
137
|
+
unless res_period.exists?
|
138
|
+
if (child = resolutions[res_period.next])
|
139
|
+
res_period.links << child.link
|
140
|
+
end
|
141
|
+
res_period.store
|
142
|
+
if (parent = resolutions[res_period.prev])
|
143
|
+
parent.update_links!(res_period.link)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def save
|
150
|
+
resolution_docs
|
151
|
+
data = @attributes
|
152
|
+
store
|
153
|
+
self.key = riak_object.key
|
154
|
+
linked_res = resolutions[self.class.resolution_period]
|
155
|
+
linked_res.update_links!(make_links)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Timemaster
|
2
|
+
module Extensions
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def time_formats
|
6
|
+
{ :year => '%Y',
|
7
|
+
:month => '%m',
|
8
|
+
:day => '%d',
|
9
|
+
:hour => '%H',
|
10
|
+
:minute => '%M',
|
11
|
+
:second => '%S'}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Timemaster::Extensions.time_formats.each do |k, v|
|
17
|
+
Date::DATE_FORMATS.update(k => v)
|
18
|
+
Time::DATE_FORMATS.update(k => v)
|
19
|
+
end
|
20
|
+
|
21
|
+
class Range
|
22
|
+
##
|
23
|
+
# Takes a range and converts it to an array of months
|
24
|
+
#
|
25
|
+
# (Time.now..1.day.from_now).to_hours
|
26
|
+
#
|
27
|
+
def to_months
|
28
|
+
return if first > last
|
29
|
+
arr = []
|
30
|
+
time = first
|
31
|
+
while time <= last
|
32
|
+
arr << time
|
33
|
+
time += 1.month
|
34
|
+
end
|
35
|
+
return arr
|
36
|
+
end
|
37
|
+
##
|
38
|
+
# Takes a range and converts it to an array of days
|
39
|
+
#
|
40
|
+
# (Time.now..7.days.from_now).to_days
|
41
|
+
#
|
42
|
+
def to_days
|
43
|
+
return if first > last
|
44
|
+
arr = []
|
45
|
+
time = first
|
46
|
+
while time <= last
|
47
|
+
arr << time
|
48
|
+
time += 1.day
|
49
|
+
end
|
50
|
+
return arr
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Takes a range and converts it to an array of hours
|
55
|
+
#
|
56
|
+
# (Time.now..1.day.from_now).to_hours
|
57
|
+
#
|
58
|
+
def to_hours
|
59
|
+
return if first > last
|
60
|
+
arr = []
|
61
|
+
time = first
|
62
|
+
while time <= last
|
63
|
+
arr << time
|
64
|
+
time += 1.hour
|
65
|
+
end
|
66
|
+
return arr
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Takes a range and converts it to an array of minutes
|
71
|
+
#
|
72
|
+
# (Time.now..1.day.from_now).to_hours
|
73
|
+
#
|
74
|
+
def to_minutes
|
75
|
+
return if first > last
|
76
|
+
arr = []
|
77
|
+
time = first
|
78
|
+
while time <= last
|
79
|
+
arr << time
|
80
|
+
time += 1.minute
|
81
|
+
end
|
82
|
+
return arr
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Timemaster
|
2
|
+
module Helpers
|
3
|
+
def bucket
|
4
|
+
@bucket ||= Chronos.riak.bucket(bucket_name)
|
5
|
+
end
|
6
|
+
|
7
|
+
def riak_object
|
8
|
+
@riak_object ||= bucket.new(key)
|
9
|
+
end
|
10
|
+
|
11
|
+
delegate :walk, :links, :store, :data, :to => :riak_object
|
12
|
+
|
13
|
+
def path
|
14
|
+
@path ||= ['', 'riak', bucket_name, key].join('/')
|
15
|
+
end
|
16
|
+
|
17
|
+
def exists?
|
18
|
+
@exists ||= (key.blank? ? false : bucket.exists?(key))
|
19
|
+
end
|
20
|
+
|
21
|
+
def link_for(tag = nil)
|
22
|
+
Riak::Link.new(path, tag)
|
23
|
+
end
|
24
|
+
|
25
|
+
def walk_spec(tag = nil, keep = false)
|
26
|
+
Riak::WalkSpec.new(bucket_name, (tag||default_tag), keep)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Timemaster
|
2
|
+
RESOLUTIONS = [:year, :month, :day, :hour, :minute, :second]
|
3
|
+
class Resolution
|
4
|
+
include Helpers
|
5
|
+
|
6
|
+
def self.index(resolution)
|
7
|
+
RESOLUTIONS.index(resolution)
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :name, :time
|
11
|
+
def initialize(name, time)
|
12
|
+
@name = name
|
13
|
+
@time = case time
|
14
|
+
when Time then
|
15
|
+
time
|
16
|
+
when String
|
17
|
+
Time.utc(*time.split('_'))
|
18
|
+
when Nil
|
19
|
+
Time.now.utc
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def index
|
24
|
+
@index ||= self.class.index(name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_tag
|
28
|
+
return @tag if @tag
|
29
|
+
return nil unless @time
|
30
|
+
@tag = @time.to_s(name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def prev
|
34
|
+
(index >= 1) ? RESOLUTIONS[index - 1] : nil
|
35
|
+
end
|
36
|
+
|
37
|
+
def next
|
38
|
+
RESOLUTIONS[index + 1]
|
39
|
+
end
|
40
|
+
|
41
|
+
def bucket_name
|
42
|
+
@bucket_name ||= name.to_s.tableize
|
43
|
+
end
|
44
|
+
|
45
|
+
def update_links!(*args)
|
46
|
+
obj = bucket.get(key)
|
47
|
+
obj.links.merge args.flatten
|
48
|
+
obj.store
|
49
|
+
end
|
50
|
+
|
51
|
+
def key
|
52
|
+
return @key if @key
|
53
|
+
# join string up to resolution and user to format time
|
54
|
+
return @key = nil if index.blank?
|
55
|
+
@key = RESOLUTIONS[0..index].inject(''){|str, res| "#{str}_#{time.to_s(res)}"}[1..-1]
|
56
|
+
end
|
57
|
+
|
58
|
+
def link
|
59
|
+
@link ||= link_for(default_tag)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/test/teststrap.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'riot'
|
3
|
+
require 'chronos'
|
4
|
+
require 'timecop'
|
5
|
+
|
6
|
+
Chronos.riak.port = 8091
|
7
|
+
|
8
|
+
CONTROLLERS = %w(users posts settings photos)
|
9
|
+
ACTIONS = %w(index new create edit update destroy)
|
10
|
+
|
11
|
+
class Request
|
12
|
+
include Chronos::Document
|
13
|
+
|
14
|
+
resolution :minute
|
15
|
+
|
16
|
+
tag :controller_name
|
17
|
+
tag :action_name
|
18
|
+
|
19
|
+
def self.make
|
20
|
+
new(:controller_name => CONTROLLERS.pick,
|
21
|
+
:action_name => ACTIONS.pick,
|
22
|
+
:request_time => 5.of{ 60 + rand(40)}.sum)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.gen
|
26
|
+
make.save
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: timemaster
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- brianthecoder
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-06-30 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: yard
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: riak-client
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: activesupport
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: hashie
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
version: "0"
|
75
|
+
type: :runtime
|
76
|
+
version_requirements: *id004
|
77
|
+
description: Creates buckets for a given resolution and will create all the appropriate links
|
78
|
+
email: wbsmith83@gmail.com
|
79
|
+
executables: []
|
80
|
+
|
81
|
+
extensions: []
|
82
|
+
|
83
|
+
extra_rdoc_files:
|
84
|
+
- LICENSE
|
85
|
+
- README.rdoc
|
86
|
+
- TODO
|
87
|
+
files:
|
88
|
+
- .document
|
89
|
+
- .gitignore
|
90
|
+
- LICENSE
|
91
|
+
- README.rdoc
|
92
|
+
- Rakefile
|
93
|
+
- TODO
|
94
|
+
- VERSION
|
95
|
+
- examples/request.rb
|
96
|
+
- lib/timemaster.rb
|
97
|
+
- lib/timemaster/document.rb
|
98
|
+
- lib/timemaster/extensions.rb
|
99
|
+
- lib/timemaster/helpers.rb
|
100
|
+
- lib/timemaster/resolution.rb
|
101
|
+
- lib/timemaster/version.rb
|
102
|
+
- test/chronos_test.rb
|
103
|
+
- test/teststrap.rb
|
104
|
+
has_rdoc: true
|
105
|
+
homepage: http://github.com/BrianTheCoder/chronos
|
106
|
+
licenses: []
|
107
|
+
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options:
|
110
|
+
- --charset=UTF-8
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
none: false
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
hash: 3
|
119
|
+
segments:
|
120
|
+
- 0
|
121
|
+
version: "0"
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
hash: 3
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
version: "0"
|
131
|
+
requirements: []
|
132
|
+
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 1.3.7
|
135
|
+
signing_key:
|
136
|
+
specification_version: 3
|
137
|
+
summary: A way to easily store time based data scalably in riak
|
138
|
+
test_files:
|
139
|
+
- test/chronos_test.rb
|
140
|
+
- test/teststrap.rb
|
141
|
+
- examples/request.rb
|