creation_report 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
+