creation_report 0.0.3

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/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
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,29 @@
1
+ = CreationReport
2
+
3
+
4
+ CreationReport is an easy way to visualize how many instances of each model are being created over time.
5
+ Keep in mind that it cannot keep track of rows that have been deleted.
6
+
7
+ Note: This plugin requires 'gchartrb'. The following line should go in your environment.rb file:
8
+ config.gem 'gchartrb', :lib => 'google_chart'
9
+
10
+
11
+ Example
12
+ =======
13
+
14
+ # MODEL
15
+ def User < ActiveRecord::Base
16
+ include CreationReport # Make sure that this is in your model
17
+
18
+ # the rest of your code
19
+ end
20
+
21
+ # CONTROLLER
22
+ def usage
23
+ @creations_by_day_chart = User.creations_by_day_chart
24
+ @creations_by_hour_chart = User.creations_by_hour_of_day_chart
25
+ end
26
+
27
+ # VIEW
28
+ <img src="<%= @creations_by_day_chart.to_url %>" alt="Google Chart" class="google_chart" />
29
+ <img src="<%= @creations_by_hour_chart.to_url %>" alt="Google Chart" class="google_chart" />
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'CreationReport'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake/testtask'
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << 'lib'
32
+ t.libs << 'test'
33
+ t.pattern = 'test/**/*_test.rb'
34
+ t.verbose = false
35
+ end
36
+
37
+
38
+ task :default => :test
@@ -0,0 +1,3 @@
1
+ module CreationReport
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,96 @@
1
+ require 'data_set'
2
+ require 'data_set/hourly_data_set'
3
+ require 'data_set/daily_data_set'
4
+ require 'data_set/day_of_week_data_set'
5
+ require 'data_set/hour_of_day_data_set'
6
+ require 'data_set/monthly_data_set'
7
+
8
+ module CreationReport
9
+
10
+ def self.append_features(base)
11
+ super
12
+ if base.superclass == ActiveRecord::Base
13
+ base.extend(ClassMethods)
14
+ else
15
+ raise "CreationReport can only be included in ActiveRecord subclasses."
16
+ end
17
+ end
18
+
19
+ module ClassMethods
20
+ @@number_of_days = 1000
21
+
22
+ def created_by_hour
23
+ DataSet::HourlyDataSet.new(
24
+ count(
25
+ :group => "DATE_FORMAT(#{table_name}.created_at,'%Y-%m-%d %h')",
26
+ :order => "#{table_name}.id ASC",
27
+ :conditions => ["#{table_name}.created_at > ?", 24.hours.ago]
28
+ ), 24
29
+ )
30
+ end
31
+
32
+ def created_by_day
33
+ DataSet::DailyDataSet.new(
34
+ count(
35
+ :group => "DATE(#{table_name}.created_at)",
36
+ :order => "#{table_name}.id ASC",
37
+ :conditions => ["#{table_name}.created_at > ?", report_start_time]
38
+ ), @@number_of_days
39
+ )
40
+ end
41
+
42
+ def created_by_hour_of_day
43
+ DataSet::HourOfDayDataSet.new(
44
+ count(
45
+ :group => "DATE_FORMAT(created_at, '%k')",
46
+ :order => "#{table_name}.id ASC",
47
+ :conditions => ["created_at > ?", report_start_time]
48
+ )
49
+ )
50
+ end
51
+
52
+ def average_created_by_day
53
+ created_by_day.values.sum.to_f / created_by_day.values.length.to_f
54
+ end
55
+
56
+ def average_created_at_this_hour
57
+ created_by_day.values.at( Time.now.hour )
58
+ end
59
+
60
+ def creations_by_day_chart
61
+ dataset = created_by_day
62
+ GoogleChart::LineChart.new('600x150', "#{self.table_name.upcase} CREATED IN THE LAST #{@@number_of_days} DAYS", false) do |lc|
63
+ lc.data_encoding = :extended
64
+ lc.data "Created", dataset.values, '00ff00'
65
+ lc.show_legend = false
66
+ lc.title_color = 'A5B1A0'
67
+ lc.title_font_size = '10'
68
+ lc.max_value dataset.max_value
69
+ lc.axis :y, :range => [dataset.min_value, dataset.max_value]
70
+ lc.axis :x, :labels => dataset.date_labels
71
+ lc.grid :y_step => 50, :x_step => 25, :length_segment => 2, :length_blank => 10
72
+ end
73
+ end
74
+
75
+ def creations_by_hour_of_day_chart
76
+ dataset = created_by_hour_of_day
77
+ GoogleChart::LineChart.new('600x150', "#{self.table_name.upcase} CREATED FOR EACH HOUR", false) do |lc|
78
+ lc.data "Created", dataset.values, '00ff00'
79
+ lc.show_legend = false
80
+ lc.title_color = 'A5B1A0'
81
+ lc.title_font_size = '10'
82
+ lc.max_value dataset.max_value
83
+ lc.axis :y, :range => [dataset.min_value, dataset.max_value]
84
+ lc.axis :x, :labels => dataset.hours.to_a
85
+ lc.grid :y_step => 50, :x_step => 100/11.5, :length_segment => 2, :length_blank => 10
86
+ end
87
+ end
88
+
89
+ protected
90
+ def report_start_time
91
+ @@number_of_days.days.ago.beginning_of_day
92
+ end
93
+
94
+ end
95
+
96
+ end
@@ -0,0 +1,50 @@
1
+ class DataSet::DailyDataSet < DataSet
2
+
3
+ def initialize( point_array, count = 30 )
4
+
5
+ @datapoints ||= {} #[["2008-06-01", 200.58], ["2008-06-02", 205.39]]
6
+ @count = count
7
+
8
+ point_array.each do |date, value|
9
+ value = value.to_f
10
+ @datapoints[date.to_s] = value
11
+ end
12
+
13
+ fill_with_zeroes(@count)
14
+ end
15
+
16
+ # Array of dates corresponding to datapoints in "2009-11-18" format
17
+ def dates
18
+ @datapoints.collect{|point| point[0]}
19
+ end
20
+
21
+ # Array of dates in "Nov 18" format corresponding to datapoints
22
+ # at one week increments working backwords from today.
23
+ # Compare today's DOW ("Mon") to each date in the array, and only return "Nov 18" for dates that match the DOW.
24
+ def date_labels
25
+ if @count < 90
26
+ dates.collect { |date| date.to_date.strftime('%d') == Time.now.strftime('%a') ? date.to_date.strftime("%b %e") : '' }
27
+ else
28
+ dates.collect { |date| date.to_date.strftime('%d') == '01' ? date.to_date.strftime("%b %e") : '' }
29
+ end
30
+ end
31
+
32
+ def full_weeks_in_dataset
33
+ @count.to_i / 7
34
+ end
35
+
36
+ # Array containing month names corresponding to datapoint positions which represent the first day of the month.
37
+ # ['','','December','','']
38
+ def month_labels
39
+ dates.collect{|date| date.to_date.day==1 ? date.to_date.strftime("%B") : ''}
40
+ end
41
+
42
+ protected
43
+ def fill_with_zeroes(days)
44
+ (0..@count).each do |i|
45
+ @datapoints[i.days.ago.to_date.to_s] ||= 0
46
+ end
47
+
48
+ @datapoints = @datapoints.sort
49
+ end
50
+ end
@@ -0,0 +1,26 @@
1
+ class DataSet::DayOfWeekDataSet < DataSet
2
+
3
+ def initialize( point_array )
4
+ @datapoints ||= {'Mon'=>0, 'Tue'=>0, 'Wed'=> 0, 'Thu'=>0, 'Fri'=>0, 'Sat'=>0, 'Sun'=>0}
5
+
6
+ point_array.each do |day_of_week, value|
7
+ value = value.to_f
8
+ @datapoints[day_of_week] = value
9
+ end
10
+ end
11
+
12
+ def days
13
+ %w{Mon Tue Wed Thu Fri Sat Sun}
14
+ end
15
+
16
+ def values
17
+ [ @datapoints['Mon'],
18
+ @datapoints['Tue'],
19
+ @datapoints['Wed'],
20
+ @datapoints['Thu'],
21
+ @datapoints['Fri'],
22
+ @datapoints['Sat'],
23
+ @datapoints['Sun']]
24
+ end
25
+
26
+ end
@@ -0,0 +1,25 @@
1
+ class DataSet::HourOfDayDataSet < DataSet
2
+
3
+ def initialize( point_array )
4
+ @datapoints = {}
5
+ hours.each do |hour|
6
+ @datapoints[hour] = 0
7
+ end
8
+
9
+ point_array.each do |hour_of_day, value|
10
+ value = value.to_f
11
+ @datapoints[hour_of_day.to_i] = value
12
+ end
13
+
14
+ @datapoints = @datapoints.sort
15
+ end
16
+
17
+ def hours
18
+ (0..23)
19
+ end
20
+
21
+ def values
22
+ hours.collect{|hour| @datapoints[hour][1]}
23
+ end
24
+
25
+ end
@@ -0,0 +1,31 @@
1
+ class DataSet::HourlyDataSet < DataSet
2
+
3
+ def initialize( point_array, count = 24 )
4
+
5
+ @datapoints ||= {} #[["2008-06-01 12", 200.58], ["2008-06-02 13", 205.39]]
6
+ @count = count
7
+
8
+ point_array.each do |date, value|
9
+ value = value.to_f
10
+ @datapoints[date.to_s] = value
11
+ end
12
+
13
+ fill_with_zeroes(@count)
14
+ end
15
+
16
+ # Array of dates corresponding to datapoints in "2009-11-18" format
17
+ def dates
18
+ @datapoints.collect{|point| point[0]}
19
+ end
20
+
21
+ protected
22
+ def fill_with_zeroes( hours )
23
+ puts "Filling to #{@count}..."
24
+ (0..@count).each do |i|
25
+ puts "Adding #{i.hours.ago.strftime("%Y-%m-%d %H")}"
26
+ @datapoints[i.hours.ago.strftime("%Y-%m-%d %H")] ||= 0
27
+ end
28
+
29
+ @datapoints = @datapoints.sort
30
+ end
31
+ end
@@ -0,0 +1,49 @@
1
+ class DataSet::MonthlyDataSet < DataSet
2
+
3
+ def initialize( point_array, count = 24 )
4
+
5
+ @datapoints ||= {} #[["2008-06", 200.58], ["2008-07", 205.39]]
6
+ @count = count
7
+
8
+ point_array.each do |date, value|
9
+ value = value.to_f
10
+ @datapoints[date] = value
11
+ end
12
+ fill_with_zeroes(@count)
13
+ truncate_datapoints
14
+ end
15
+
16
+ # Return array of months in '2009-11' format corresponding to datapoints
17
+ def months
18
+ @datapoints.collect{ |point| point[0] }
19
+ end
20
+
21
+ # Array of abbreviated months ('Jan', 'Feb') corresponding to datapoints
22
+ def month_labels
23
+ months.collect{ |month|
24
+ "#{month}-01".to_date.strftime("%b")
25
+ }
26
+ end
27
+
28
+ # Array containing full year (2009) x-axis labels stacked beneath month labels that are "Jan"
29
+ def year_labels
30
+ months.collect{|month| "#{month}-01".to_date.month==1 ? "#{month}-01".to_date.year : '' }
31
+ end
32
+
33
+
34
+ protected
35
+ # Set dates that don't have values to 0.
36
+ # This method turns the @datapoints hash into an array.
37
+ def fill_with_zeroes(month_count)
38
+ (0..month_count-1).each do |i|
39
+ @datapoints[i.months.ago.to_date.strftime("%Y-%m")] ||= 0
40
+ end
41
+ @datapoints = @datapoints.sort
42
+ end
43
+
44
+ # Ditch the datapoints that we aren't interested in
45
+ def truncate_datapoints
46
+ return unless @datapoints.length > @count
47
+ @datapoints = @datapoints.slice( @datapoints.length - @count, @count)
48
+ end
49
+ end
data/lib/data_set.rb ADDED
@@ -0,0 +1,53 @@
1
+ class DataSet
2
+
3
+ attr_accessor :datapoints
4
+ attr_reader :max_value, :min_value, :max_date, :min_date, :count
5
+
6
+ # The standard initialize function creates a hash out of an array of points.
7
+ def initialize( point_array )
8
+ @datapoints ||= {}
9
+ @count = count || 30
10
+
11
+ point_array.each do |x_value, y_value|
12
+ y_value = y_value.to_f
13
+ @datapoints[x_value] = y_value
14
+ end
15
+ end
16
+
17
+ def values_for_google_chart
18
+ values.join(',')
19
+ end
20
+
21
+ def min_value
22
+ values.min
23
+ end
24
+
25
+ def max_value
26
+ values.max
27
+ end
28
+
29
+ def min_date
30
+ dates.min
31
+ end
32
+
33
+ def max_date
34
+ dates.max
35
+ end
36
+
37
+ def dates
38
+ @datapoints.collect{|point| point[0]}
39
+ end
40
+
41
+ def values
42
+ @datapoints.collect{|point| point[1]}
43
+ end
44
+
45
+ def value_for_date(date)
46
+ begin
47
+ return @datapoints.detect{|point| point[0]==date}[1]
48
+ rescue
49
+ raise "That date is not in the dataset."
50
+ end
51
+ end
52
+
53
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :creation_report do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: creation_report
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
11
+ platform: ruby
12
+ authors:
13
+ - Jon Collier
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-05-18 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rails
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 3
31
+ - 2
32
+ version: "3.2"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: gchartrb
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: mysql
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: sqlite3
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: :development
76
+ version_requirements: *id004
77
+ description: ""
78
+ email:
79
+ - gem@joncollier.com
80
+ executables: []
81
+
82
+ extensions: []
83
+
84
+ extra_rdoc_files: []
85
+
86
+ files:
87
+ - lib/creation_report/version.rb
88
+ - lib/creation_report.rb
89
+ - lib/data_set/daily_data_set.rb
90
+ - lib/data_set/day_of_week_data_set.rb
91
+ - lib/data_set/hour_of_day_data_set.rb
92
+ - lib/data_set/hourly_data_set.rb
93
+ - lib/data_set/monthly_data_set.rb
94
+ - lib/data_set.rb
95
+ - lib/tasks/creation_report_tasks.rake
96
+ - MIT-LICENSE
97
+ - Rakefile
98
+ - README.rdoc
99
+ homepage: ""
100
+ licenses: []
101
+
102
+ post_install_message:
103
+ rdoc_options: []
104
+
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ hash: 3
113
+ segments:
114
+ - 0
115
+ version: "0"
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: 3
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ requirements: []
126
+
127
+ rubyforge_project:
128
+ rubygems_version: 1.8.5
129
+ signing_key:
130
+ specification_version: 3
131
+ summary: Easily generate graphs for ActiveRecord object creation.
132
+ test_files: []
133
+