mancora 0.0.1
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/.gitignore +17 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +130 -0
- data/Rakefile +7 -0
- data/lib/generators/mancora/install/install_generator.rb +25 -0
- data/lib/generators/mancora/install/templates/create_mancora_stats.rb +13 -0
- data/lib/generators/mancora/install/templates/mancora.rb +28 -0
- data/lib/mancora/railtie.rb +11 -0
- data/lib/mancora/stat.rb +5 -0
- data/lib/mancora/version.rb +3 -0
- data/lib/mancora/widget.rb +136 -0
- data/lib/mancora.rb +26 -0
- data/lib/tasks/tasks.rake +4 -0
- data/mancora.gemspec +23 -0
- metadata +101 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2013 Caleb
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Mancora [](http://travis-ci.org/cbron/mancora)
|
|
2
|
+
|
|
3
|
+
Easily save counts of models or specific model queries on regular intervals into a single table to use for statistics.
|
|
4
|
+
|
|
5
|
+
For example, you can set up a count on the number of subscribers you get per hour, day, week, etc. That number will be saved in a table in the database with which you can do whatever you want (I'll show you how to graph it below). The other main option is a total count, basically a `User.count` for each of those time periods. Finally you can specify a custom class method to call, completely seperate from Mancora.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
Add this line to your application's Gemfile
|
|
11
|
+
|
|
12
|
+
gem 'mancora'
|
|
13
|
+
|
|
14
|
+
And then execute
|
|
15
|
+
|
|
16
|
+
bundle
|
|
17
|
+
|
|
18
|
+
To add it to your application
|
|
19
|
+
|
|
20
|
+
rails g mancora:install
|
|
21
|
+
rake db:migrate # Creates a mancora_stats table, use `Mancora::Stat` to access it
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Then setup your lib/mancora.rb file. Only class_name and intervals are required
|
|
26
|
+
|
|
27
|
+
Mancora.widgets do
|
|
28
|
+
|
|
29
|
+
widget :errors_per_hour do
|
|
30
|
+
class_name Requests
|
|
31
|
+
intervals :hourly
|
|
32
|
+
conditions :name => "error"
|
|
33
|
+
end
|
|
34
|
+
#this generates: Request.where(:name => "error", :created_at => 1.hour.ago.beginning_of_hour..1.hour.ago.end_of_hour).count
|
|
35
|
+
|
|
36
|
+
widget :subscribers_count do
|
|
37
|
+
class_name Subscriber
|
|
38
|
+
intervals [:hourly, :daily, :monthly, :yearly]
|
|
39
|
+
field :registered_at
|
|
40
|
+
time 1.day.ago #lag by one day
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
widget :total_subscribers_count do
|
|
44
|
+
class_name Subscriber
|
|
45
|
+
intervals [:daily, :weekly, :monthly, :yearly]
|
|
46
|
+
count_type :total
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
widget :custm_promo_codes
|
|
50
|
+
class_name Subscriber
|
|
51
|
+
class_method generate_promo_code_hash
|
|
52
|
+
intervals :monthly
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
Options
|
|
58
|
+
|
|
59
|
+
key | function
|
|
60
|
+
--- | ---
|
|
61
|
+
class_name | The class name you will be querying on
|
|
62
|
+
intervals | The interval you want to collect stats on
|
|
63
|
+
count_type | The type of count for this interval. `:timed` will query only this time period and is the default. `:total` will just do a total count on that modal, it cannot be backfilled.
|
|
64
|
+
conditions | Additional conditions for query as a hash
|
|
65
|
+
field | Field other than created_at to query on. Not included if count_type is :total.
|
|
66
|
+
time | Amount of time to lag by: 1.day, 1.hour.
|
|
67
|
+
class_method | Custom class method to call, will not insert row in database. All this does is call the method at run time
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
Now to run it
|
|
71
|
+
|
|
72
|
+
#in the console
|
|
73
|
+
Mancora.run
|
|
74
|
+
|
|
75
|
+
#backfill the last 36 hours
|
|
76
|
+
Mancora.run(36)
|
|
77
|
+
|
|
78
|
+
#via rake
|
|
79
|
+
rake mancora
|
|
80
|
+
|
|
81
|
+
Finally setup a cron to run **every hour**. You could use the whenever gem but personally I still like:
|
|
82
|
+
|
|
83
|
+
# Every hour at 5 minutes in
|
|
84
|
+
5 */1 * * * cd /rails_path && /usr/local/bin/rake RAILS_ENV=production mancora >> /rails_path/log/mancora.log 2>&1
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
Result in db (notice subscribers_count has a day lag, and daily includes the time zone)
|
|
89
|
+
|
|
90
|
+
id | name | intervals | count | start | end
|
|
91
|
+
--- | --- | --- | --- | --- | ---
|
|
92
|
+
1 | errors | hourly | 4 | 2013-03-01 21:00:00 | 2013-03-01 21:59:59
|
|
93
|
+
2 | subscribers_count | hourly | 2 | 2013-02-28 21:00:00 | 2013-02-28 21:59:59
|
|
94
|
+
3 | total_subscribers_count | daily | 972 | 2013-02-27 07:00:00 | 2013-02-28 06:59:59
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
## Graphing the results
|
|
98
|
+
|
|
99
|
+
I ended up using Morris: http://www.oesmith.co.uk/morris.js/
|
|
100
|
+
|
|
101
|
+
After installing Raphael/Morris its as easy as:
|
|
102
|
+
|
|
103
|
+
Controller
|
|
104
|
+
|
|
105
|
+
@subscribers_today = Mancora::Stat.where(:name => "subscribers_count", :intervals => :hourly).limit(24).order("start desc")
|
|
106
|
+
|
|
107
|
+
View
|
|
108
|
+
|
|
109
|
+
%h1 Subscribers today
|
|
110
|
+
=content_tag :div, "", id: "subscribers_chart", data: {subscriberstoday: @subscribers_today}
|
|
111
|
+
|
|
112
|
+
Coffeescript
|
|
113
|
+
|
|
114
|
+
Morris.Line
|
|
115
|
+
element: "subscribers_chart"
|
|
116
|
+
data: $("#subscribers_chart").data('subscribers')
|
|
117
|
+
xkey: "start"
|
|
118
|
+
ykeys: ["count"]
|
|
119
|
+
labels: ["Count"]
|
|
120
|
+
hideHover: false
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
## Contributing
|
|
124
|
+
|
|
125
|
+
1. Fork it
|
|
126
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
127
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
128
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
129
|
+
5. Create new Pull Request
|
|
130
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'rails/generators/migration'
|
|
2
|
+
|
|
3
|
+
module Mancora
|
|
4
|
+
module Generators
|
|
5
|
+
class InstallGenerator < ::Rails::Generators::Base
|
|
6
|
+
include Rails::Generators::Migration
|
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
8
|
+
desc "add the migrations"
|
|
9
|
+
|
|
10
|
+
def self.next_migration_number(path)
|
|
11
|
+
unless @prev_migration_nr
|
|
12
|
+
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
|
13
|
+
else
|
|
14
|
+
@prev_migration_nr += 1
|
|
15
|
+
end
|
|
16
|
+
@prev_migration_nr.to_s
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def copy_migrations
|
|
20
|
+
migration_template "create_mancora_stats.rb", "db/migrate/create_mancora_stats.rb"
|
|
21
|
+
copy_file "mancora.rb", "lib/mancora.rb"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Mancora.widgets do
|
|
2
|
+
|
|
3
|
+
# widget :errors do
|
|
4
|
+
# class_name ManualStat
|
|
5
|
+
# intervals [:hourly, :daily, :weekly, :monthly, :yearly]
|
|
6
|
+
# conditions :name => "error"
|
|
7
|
+
# end
|
|
8
|
+
|
|
9
|
+
# widget :subscribers_count do
|
|
10
|
+
# class_name Subscriber
|
|
11
|
+
# intervals :hourly
|
|
12
|
+
# field :registered_at
|
|
13
|
+
# time 1.day.ago #lag by one day
|
|
14
|
+
# end
|
|
15
|
+
|
|
16
|
+
# widget :total_subscribers_count do
|
|
17
|
+
# class_name Subscriber
|
|
18
|
+
# intervals [:daily, :weekly, :monthly, :yearly]
|
|
19
|
+
# count_type :total
|
|
20
|
+
# end
|
|
21
|
+
|
|
22
|
+
# widget :custm_promo_codes
|
|
23
|
+
# class_name Subscriber
|
|
24
|
+
# class_method generate_promo_code_hash
|
|
25
|
+
# intervals :monthly
|
|
26
|
+
# end
|
|
27
|
+
|
|
28
|
+
end
|
data/lib/mancora/stat.rb
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
class Widget
|
|
2
|
+
attr_accessor :name, :class_name, :intervals, :count_type, :conditions,
|
|
3
|
+
:start, :end, :time, :field, :query, :class_method
|
|
4
|
+
|
|
5
|
+
def initialize(name, backfill = 0, &block)
|
|
6
|
+
@name = name
|
|
7
|
+
@conditions = {}
|
|
8
|
+
instance_eval &block
|
|
9
|
+
|
|
10
|
+
lazy_names
|
|
11
|
+
|
|
12
|
+
#run all backfills plus the original @time
|
|
13
|
+
backfill.downto(0) do |b|
|
|
14
|
+
b != 0 ? @backfilling = true : @backfilling = false
|
|
15
|
+
@run_time = @time - b.hours
|
|
16
|
+
|
|
17
|
+
@intervals.each do |i|
|
|
18
|
+
time_interval = @query.blank? ? get_interval(i) : {}
|
|
19
|
+
all_conditions = @conditions.merge(time_interval)
|
|
20
|
+
run(i, all_conditions) if should_i_run?(i)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def class_name(str)
|
|
26
|
+
@class_name = str
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def intervals(opts)
|
|
30
|
+
@intervals = opts.instance_of?(Array)? opts : [opts]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def count_type(str)
|
|
34
|
+
@count_type = str
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def conditions(str)
|
|
38
|
+
@conditions = str
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def time(str)
|
|
42
|
+
@time = str
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def field(str)
|
|
46
|
+
@field = str
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def query(str)
|
|
50
|
+
@query = str
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def class_method(str)
|
|
54
|
+
@class_method = str
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def lazy_names
|
|
58
|
+
@time ||= Time.now
|
|
59
|
+
@field ||= :created_at
|
|
60
|
+
@count_type ||= :timed
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def run(interval, all_conditions)
|
|
64
|
+
puts "Running " + interval.to_s + " " + self.name.to_s
|
|
65
|
+
|
|
66
|
+
if @class_method
|
|
67
|
+
@class_name.send(@class_method)
|
|
68
|
+
else
|
|
69
|
+
if @count_type == :timed
|
|
70
|
+
result = @class_name.where(all_conditions)
|
|
71
|
+
elsif @count_type == :total
|
|
72
|
+
count = (@backfilling ? nil : @class_name.where(@conditions).count)
|
|
73
|
+
elsif !@query.blank?
|
|
74
|
+
result = eval(@query)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
#create or update record, this way we can backfill without overwriting
|
|
78
|
+
obj = Mancora::Stat.find_or_initialize_by_name_and_start(name, @start)
|
|
79
|
+
|
|
80
|
+
obj.update_attributes(
|
|
81
|
+
:name => @name,
|
|
82
|
+
:start => @start,
|
|
83
|
+
:end => @end,
|
|
84
|
+
:intervals => interval,
|
|
85
|
+
:count => (@count_type == :timed ? result.count : count)
|
|
86
|
+
)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
#given an interval symbol, return a hash with the correct conditions
|
|
91
|
+
def get_interval(interval)
|
|
92
|
+
case interval
|
|
93
|
+
when :custom
|
|
94
|
+
return {}
|
|
95
|
+
when :hourly
|
|
96
|
+
@start = (@run_time - 1.hour).beginning_of_hour
|
|
97
|
+
@end = (@run_time - 1.hour).end_of_hour
|
|
98
|
+
return {@field => @start..@end}
|
|
99
|
+
when :daily
|
|
100
|
+
@start = @run_time.yesterday.beginning_of_day
|
|
101
|
+
@end = @run_time.yesterday.end_of_day
|
|
102
|
+
return {@field => @start..@end}
|
|
103
|
+
when :weekly
|
|
104
|
+
@start = @run_time.yesterday.beginning_of_week
|
|
105
|
+
@end = @run_time.yesterday.end_of_week
|
|
106
|
+
return {@field => @start..@end}
|
|
107
|
+
when :monthly
|
|
108
|
+
@start = @run_time.yesterday.beginning_of_month
|
|
109
|
+
@end = @run_time.yesterday.end_of_month
|
|
110
|
+
return {@field => @start..@end}
|
|
111
|
+
when :yearly
|
|
112
|
+
@start = @run_time.yesterday.beginning_of_year
|
|
113
|
+
@end = @run_time.yesterday.end_of_year
|
|
114
|
+
return {@field => @start..@end}
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
#given an interval symbol, determine whether or not a query (and relative db insert) should take place
|
|
119
|
+
def should_i_run?(interval)
|
|
120
|
+
if interval == :hourly
|
|
121
|
+
true
|
|
122
|
+
elsif interval == :daily && @run_time.hour == 0
|
|
123
|
+
true
|
|
124
|
+
elsif interval == :weekly && @run_time.beginning_of_week == @run_time.beginning_of_day
|
|
125
|
+
true
|
|
126
|
+
elsif interval == :monthly && @run_time.day == 1
|
|
127
|
+
true
|
|
128
|
+
elsif interval == :yearly && @run_time.beginning_of_year == @run_time.beginning_of_day
|
|
129
|
+
true
|
|
130
|
+
else
|
|
131
|
+
false
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
end
|
data/lib/mancora.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "mancora/version"
|
|
2
|
+
require 'mancora/widget'
|
|
3
|
+
require 'mancora/stat'
|
|
4
|
+
require 'mancora/railtie' if defined?(Rails)
|
|
5
|
+
|
|
6
|
+
module Mancora
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
def self.table_name_prefix
|
|
10
|
+
'mancora_'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.run(backfill = 0)
|
|
14
|
+
@backfill = backfill
|
|
15
|
+
puts "Backfilling " + (@backfill || 0).to_s + " hours." if @backfill > 0
|
|
16
|
+
load Rails.root.join('lib', 'mancora.rb')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def widgets(hash = {}, &block)
|
|
20
|
+
instance_eval(&block) if block_given?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def widget(opt, options = {}, &block)
|
|
24
|
+
Widget.new(opt, @backfill, &block)
|
|
25
|
+
end
|
|
26
|
+
end
|
data/mancora.gemspec
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'mancora/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "mancora"
|
|
8
|
+
spec.version = Mancora::VERSION
|
|
9
|
+
spec.authors = ["cbron"]
|
|
10
|
+
spec.email = ["x@x.com"]
|
|
11
|
+
spec.description = %q{Save for counts for statistics}
|
|
12
|
+
spec.summary = %q{Easily save counts of models on regular intervals into a single table to use for statistics.}
|
|
13
|
+
spec.homepage = ""
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files`.split($/)
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_development_dependency "bundler"
|
|
22
|
+
spec.add_development_dependency "rake"
|
|
23
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: mancora
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- cbron
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2013-03-07 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: bundler
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :development
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ! '>='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '0'
|
|
30
|
+
- !ruby/object:Gem::Dependency
|
|
31
|
+
name: rake
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
33
|
+
none: false
|
|
34
|
+
requirements:
|
|
35
|
+
- - ! '>='
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '0'
|
|
38
|
+
type: :development
|
|
39
|
+
prerelease: false
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ! '>='
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
description: Save for counts for statistics
|
|
47
|
+
email:
|
|
48
|
+
- x@x.com
|
|
49
|
+
executables: []
|
|
50
|
+
extensions: []
|
|
51
|
+
extra_rdoc_files: []
|
|
52
|
+
files:
|
|
53
|
+
- .gitignore
|
|
54
|
+
- .travis.yml
|
|
55
|
+
- Gemfile
|
|
56
|
+
- LICENSE.txt
|
|
57
|
+
- README.md
|
|
58
|
+
- Rakefile
|
|
59
|
+
- lib/generators/mancora/install/install_generator.rb
|
|
60
|
+
- lib/generators/mancora/install/templates/create_mancora_stats.rb
|
|
61
|
+
- lib/generators/mancora/install/templates/mancora.rb
|
|
62
|
+
- lib/mancora.rb
|
|
63
|
+
- lib/mancora/railtie.rb
|
|
64
|
+
- lib/mancora/stat.rb
|
|
65
|
+
- lib/mancora/version.rb
|
|
66
|
+
- lib/mancora/widget.rb
|
|
67
|
+
- lib/tasks/tasks.rake
|
|
68
|
+
- mancora.gemspec
|
|
69
|
+
homepage: ''
|
|
70
|
+
licenses:
|
|
71
|
+
- MIT
|
|
72
|
+
post_install_message:
|
|
73
|
+
rdoc_options: []
|
|
74
|
+
require_paths:
|
|
75
|
+
- lib
|
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
77
|
+
none: false
|
|
78
|
+
requirements:
|
|
79
|
+
- - ! '>='
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
segments:
|
|
83
|
+
- 0
|
|
84
|
+
hash: 92013857095353279
|
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
|
+
none: false
|
|
87
|
+
requirements:
|
|
88
|
+
- - ! '>='
|
|
89
|
+
- !ruby/object:Gem::Version
|
|
90
|
+
version: '0'
|
|
91
|
+
segments:
|
|
92
|
+
- 0
|
|
93
|
+
hash: 92013857095353279
|
|
94
|
+
requirements: []
|
|
95
|
+
rubyforge_project:
|
|
96
|
+
rubygems_version: 1.8.25
|
|
97
|
+
signing_key:
|
|
98
|
+
specification_version: 3
|
|
99
|
+
summary: Easily save counts of models on regular intervals into a single table to
|
|
100
|
+
use for statistics.
|
|
101
|
+
test_files: []
|