jzimmek-reportme 0.0.5

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jan Zimmek
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
+ = report_me
2
+
3
+ ReportMe is a thin ruby wrapper around your reporting sql queries which empowers you to automate, historicize, graph and mail them in an easy manner.
4
+
5
+ == Usage
6
+
7
+ ReportFactory.create do
8
+ report :visits do
9
+ source do |von, bis|
10
+ <<-SQL
11
+ select
12
+ date(v.created_at) as datum,
13
+ channel,
14
+ count(1) as cnt
15
+ from
16
+ visits v
17
+ where
18
+ v.created_at between '#{von}' and '#{bis}'
19
+ group by
20
+ date(v.created_at),
21
+ channel
22
+ SQL
23
+ end
24
+ end
25
+ end
26
+
27
+ == Copyright
28
+
29
+ Copyright (c) 2009 Jan Zimmek. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,58 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "reportme"
8
+ gem.summary = "Ruby wrapper to automate sql reports"
9
+ gem.description = "ReportMe is a thin ruby wrapper around your reporting sql queries which empowers you to automate, historicize, graph and mail them in an easy manner."
10
+ gem.email = "jan.zimmek@web.de"
11
+ gem.homepage = "http://github.com/jzimmek/report_me"
12
+ gem.authors = ["Jan Zimmek"]
13
+ gem.files = FileList['lib/**/*.rb', 'bin/*', '[A-Z]*', 'test/**/*'].to_a
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/*_test.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/*_test.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+
42
+ task :default => :test
43
+
44
+ require 'rake/rdoctask'
45
+ Rake::RDocTask.new do |rdoc|
46
+ if File.exist?('VERSION.yml')
47
+ config = YAML.load(File.read('VERSION.yml'))
48
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
49
+ else
50
+ version = ""
51
+ end
52
+
53
+ rdoc.rdoc_dir = 'rdoc'
54
+ rdoc.title = "report_me #{version}"
55
+ rdoc.rdoc_files.include('README*')
56
+ rdoc.rdoc_files.include('lib/**/*.rb')
57
+ end
58
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.5
data/lib/reportme.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'activerecord'
3
+
4
+ require 'reportme/report'
5
+ require 'reportme/report_factory'
@@ -0,0 +1,45 @@
1
+ module Reportme
2
+ class Report
3
+
4
+ attr_reader :name
5
+
6
+ def initialize(name)
7
+ @name = name
8
+ @periods = [:today, :day, :week, :calendar_week, :month, :calendar_month]
9
+ end
10
+
11
+ def source(&block)
12
+ @source = block
13
+ end
14
+
15
+ def periods(*args)
16
+ unless args.blank?
17
+ @periods.clear
18
+ args.each do |period|
19
+ @periods << period
20
+ end
21
+ end
22
+ end
23
+
24
+ def wants_period?(period)
25
+ @periods.include?(period)
26
+ end
27
+
28
+ def periods
29
+
30
+ end
31
+
32
+ def sql(von, bis)
33
+ @source.call(von, bis)
34
+ end
35
+
36
+ def table_name(period)
37
+ "#{name}_#{period}"
38
+ end
39
+
40
+ def table_exist?(period)
41
+ ActiveRecord::Base.connection.select_value("show tables like '#{table_name(period)}'") != nil
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,152 @@
1
+ require 'reportme/report'
2
+
3
+ module Reportme
4
+ class ReportFactory
5
+
6
+ def self.create(&block)
7
+ rme = ReportFactory.new
8
+ rme.instance_eval(&block)
9
+ rme.run
10
+ rme
11
+ end
12
+
13
+ def initialize
14
+ @reports = []
15
+ end
16
+
17
+ def periods(today = DateTime.now)
18
+
19
+ periods = []
20
+
21
+ [:today, :day, :week, :calendar_week, :month, :calendar_month].each do |period|
22
+
23
+ von, bis = case period
24
+ when :today
25
+ [today, today]
26
+ when :day
27
+ [today - 1.day, today - 1.day]
28
+ when :week
29
+ [today - 1.day - 1.week, today - 1.day]
30
+ when :calendar_week
31
+ n = today - 1.day
32
+ [n - n.cwday + 1, n - n.cwday + 7]
33
+ when :month
34
+ [today - 1.day - 1.month, today - 1.day]
35
+ when :calendar_month
36
+ n = today - 1.month
37
+ [n.beginning_of_month, n.end_of_month]
38
+ end
39
+
40
+ periods << {:name => period, :von => von, :bis => bis}
41
+
42
+ end
43
+
44
+ periods
45
+ end
46
+
47
+ def report_information_table_name
48
+ "report_informations"
49
+ end
50
+
51
+ def report_information_table_name_exist?
52
+ ActiveRecord::Base.connection.select_value("show tables like '#{report_information_table_name}'") != nil
53
+ end
54
+
55
+ def report_exists?(name, von, bis)
56
+ ActiveRecord::Base.connection.select_value("select 1 from #{report_information_table_name} where report = '#{name}' and von = '#{von}' and bis = '#{bis}'") != nil
57
+ end
58
+
59
+ def reset
60
+ exec("drop table if exists #{report_information_table_name};")
61
+
62
+ periods.each do |period|
63
+ @reports.each do |r|
64
+ exec("drop table if exists #{r.table_name(period[:name])};")
65
+ end
66
+ end
67
+ end
68
+
69
+ def run
70
+
71
+ debug = false
72
+
73
+ unless report_information_table_name_exist?
74
+ ddl = <<-SQL
75
+ create
76
+ table report_informations
77
+ (
78
+ report varchar(255) not null,
79
+ von datetime not null,
80
+ bis datetime not null,
81
+ created_at datetime not null,
82
+ primary key (report)
83
+ )
84
+ ENGINE=InnoDB default CHARSET=utf8;
85
+ SQL
86
+ exec(ddl)
87
+ end
88
+
89
+ if debug
90
+ # just for testing
91
+ exec("truncate #{report_information_table_name};")
92
+ end
93
+
94
+ periods.each do |period|
95
+
96
+ @reports.each do |r|
97
+
98
+ next unless r.wants_period?(period[:name])
99
+
100
+ von = period[:von].strftime("%Y-%m-%d 00:00:00")
101
+ bis = period[:bis].strftime("%Y-%m-%d 23:59:59")
102
+
103
+ table_name = r.table_name(period[:name])
104
+
105
+ if debug
106
+ # drop and create table while in testing mode
107
+ exec("drop table if exists #{table_name};")
108
+ end
109
+
110
+ table_exist = r.table_exist?(period[:name])
111
+ sql = r.sql(von, bis)
112
+ report_exist = report_exists?(table_name, von, bis)
113
+
114
+ puts "report: #{r.name}_#{period[:name]} :: #{report_exist}"
115
+
116
+
117
+ unless table_exist
118
+ exec("create table #{table_name} ENGINE=InnoDB default CHARSET=utf8 as #{sql} limit 0;")
119
+ end
120
+
121
+ puts sql
122
+
123
+ # if !report_exist || period[:name] == :today
124
+ # ActiveRecord::Base.transaction do
125
+ # exec("insert into #{report_information_table_name} values ('#{table_name}', '#{von}', '#{bis}', now());") unless report_exist
126
+ #
127
+ # if period[:name] == :today
128
+ # exec("truncate #{table_name};")
129
+ # end
130
+ #
131
+ # exec("insert into #{table_name} #{sql};")
132
+ # end
133
+ # end
134
+
135
+
136
+ end
137
+ end
138
+ end
139
+
140
+ def exec(sql)
141
+ ActiveRecord::Base.connection.execute(sql)
142
+ end
143
+
144
+ def report(name, &block)
145
+ r = Report.new(name)
146
+ r.instance_eval(&block)
147
+
148
+ @reports << r
149
+ end
150
+
151
+ end
152
+ end
@@ -0,0 +1,96 @@
1
+ require 'test_helper'
2
+
3
+ class ReportMeTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ exec("use report_me_test")
7
+ exec "drop table if exists visits"
8
+ exec <<-SQL
9
+ create
10
+ table visits
11
+ (
12
+ id bigint auto_increment,
13
+ channel varchar(255),
14
+ created_at datetime,
15
+ primary key (id)
16
+ )
17
+ SQL
18
+ end
19
+
20
+ def create_visit_report_factory
21
+
22
+ rme = ReportMe::ReportFactory.create do
23
+ report :visits do
24
+ source do |von, bis|
25
+ <<-SQL
26
+ select
27
+ date('#{von}') as datum,
28
+ channel,
29
+ count(1) as cnt
30
+ from
31
+ visits
32
+ where
33
+ created_at between '#{von}' and '#{bis}'
34
+ group by
35
+ date(created_at),
36
+ channel
37
+ SQL
38
+ end
39
+ end
40
+ end
41
+
42
+ rme.reset
43
+ rme
44
+ end
45
+
46
+ def exec(sql)
47
+ ActiveRecord::Base.connection.execute(sql)
48
+ end
49
+
50
+ def one(sql)
51
+ ActiveRecord::Base.connection.select_one(sql)
52
+ end
53
+
54
+ def teardown
55
+ exec("truncate visits;");
56
+ end
57
+
58
+ should "create one visitor in the today report for channel sem" do
59
+ exec("insert into visits values (null, 'sem', now())");
60
+ create_visit_report_factory.run
61
+ assert_equal 1, one("select count(1) as cnt from visits_today where channel = 'sem' and datum = curdate()")["cnt"].to_i
62
+ end
63
+
64
+ should "create two visitors in the today report for channel sem" do
65
+ exec("insert into visits values (null, 'sem', now())");
66
+ exec("insert into visits values (null, 'sem', now())");
67
+ create_visit_report_factory.run
68
+ assert_equal 2, one("select cnt from visits_today where channel = 'sem' and datum = curdate()")["cnt"].to_i
69
+ end
70
+
71
+ should "create visitors in the today report for channel sem and seo" do
72
+ exec("insert into visits values (null, 'sem', now())");
73
+ exec("insert into visits values (null, 'sem', now())");
74
+ exec("insert into visits values (null, 'seo', now())");
75
+ exec("insert into visits values (null, 'sem', now())");
76
+ exec("insert into visits values (null, 'seo', now())");
77
+ create_visit_report_factory.run
78
+ assert_equal 2, one("select cnt from visits_today where channel = 'seo' and datum = curdate()")["cnt"].to_i
79
+ assert_equal 3, one("select cnt from visits_today where channel = 'sem' and datum = curdate()")["cnt"].to_i
80
+ end
81
+
82
+ should "create visitors in the day report for channel sem and seo" do
83
+ exec("insert into visits values (null, 'sem', date_sub(curdate(), interval 1 day));");
84
+ exec("insert into visits values (null, 'sem', date_sub(curdate(), interval 1 day));");
85
+ exec("insert into visits values (null, 'seo', date_sub(curdate(), interval 1 day));");
86
+ exec("insert into visits values (null, 'sem', date_sub(curdate(), interval 1 day));");
87
+ exec("insert into visits values (null, 'seo', date_sub(curdate(), interval 1 day));");
88
+ create_visit_report_factory.run
89
+ assert_equal 2, one("select cnt from visits_day where channel = 'seo' and datum = date_sub(curdate(), interval 1 day)")["cnt"].to_i
90
+ assert_equal 3, one("select cnt from visits_day where channel = 'sem' and datum = date_sub(curdate(), interval 1 day)")["cnt"].to_i
91
+ end
92
+
93
+ should "handle today and day periods but nothing else" do
94
+ end
95
+
96
+ end
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'report_me'
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+
9
+
10
+ class Test::Unit::TestCase
11
+ end
12
+
13
+ ActiveRecord::Base.establish_connection(:adapter => "mysql", :database => "mysql", :username => "root", :password => "root", :host => "localhost", :port => 3306)
14
+
15
+ ActiveRecord::Base.connection.execute "drop database if exists report_me_test;"
16
+ ActiveRecord::Base.connection.execute "create database report_me_test;"
17
+ ActiveRecord::Base.connection.execute "use report_me_test;"
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jzimmek-reportme
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Jan Zimmek
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-23 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: ReportMe is a thin ruby wrapper around your reporting sql queries which empowers you to automate, historicize, graph and mail them in an easy manner.
17
+ email: jan.zimmek@web.de
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - LICENSE
27
+ - README.rdoc
28
+ - Rakefile
29
+ - VERSION
30
+ - lib/reportme.rb
31
+ - lib/reportme/report.rb
32
+ - lib/reportme/report_factory.rb
33
+ - test/report_me_test.rb
34
+ - test/test_helper.rb
35
+ has_rdoc: false
36
+ homepage: http://github.com/jzimmek/report_me
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --charset=UTF-8
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.2.0
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Ruby wrapper to automate sql reports
61
+ test_files:
62
+ - test/report_me_test.rb
63
+ - test/test_helper.rb