reportable 1.1.2 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -21
- data/Rakefile +0 -3
- data/generators/reportable_jquery_flot_assets/reportable_jquery_flot_assets_generator.rb +15 -34
- data/generators/reportable_migration/reportable_migration_generator.rb +12 -32
- data/generators/reportable_raphael_assets/reportable_raphael_assets_generator.rb +19 -39
- data/lib/saulabs/reportable.rb +2 -4
- data/lib/saulabs/reportable/cumulated_report.rb +1 -1
- data/lib/saulabs/reportable/railtie.rb +12 -1
- data/lib/saulabs/reportable/report_cache.rb +16 -4
- data/lib/saulabs/reportable/report_tag_helper.rb +4 -4
- data/lib/saulabs/reportable/reporting_period.rb +2 -1
- data/lib/saulabs/reportable/result_set.rb +8 -2
- data/spec/classes/cumulated_report_spec.rb +1 -1
- data/spec/classes/grouping_spec.rb +1 -1
- data/spec/classes/report_cache_spec.rb +32 -13
- data/spec/classes/report_spec.rb +5 -5
- data/spec/classes/reporting_period_spec.rb +11 -1
- data/spec/db/database.yml +2 -2
- data/spec/other/report_method_spec.rb +11 -8
- data/spec/other/report_tag_helper_spec.rb +7 -1
- data/spec/spec_helper.rb +31 -11
- metadata +42 -73
- data/rails/init.rb +0 -11
- data/spec/boot.rb +0 -22
data/README.md
CHANGED
@@ -60,27 +60,9 @@ To install the Reportable gem, simply run
|
|
60
60
|
|
61
61
|
[sudo] gem install reportable
|
62
62
|
|
63
|
-
### Rails
|
63
|
+
### Rails 3.x
|
64
64
|
|
65
|
-
To install Reportable for Rails
|
66
|
-
|
67
|
-
config.gem 'reportable', :lib => 'saulabs/reportable'
|
68
|
-
|
69
|
-
and generate the migration that create reportable's cache table:
|
70
|
-
|
71
|
-
./script/generate reportable_migration
|
72
|
-
|
73
|
-
If you want to use reportable's JavaScript graph output format, you also have to generate the JavaScript files:
|
74
|
-
|
75
|
-
./script/generate reportable_raphael_assets
|
76
|
-
|
77
|
-
if you want to use [Raphael](http://raphaeljs.com/) or if you want to use [jQuery](http://jquery.com/) and [flot](http://code.google.com/p/flot/):
|
78
|
-
|
79
|
-
./script/generate reportable_jquery_flot_assets
|
80
|
-
|
81
|
-
### Rails 3.0
|
82
|
-
|
83
|
-
To install Reportable for Rails 3.0, add it to your application's Gemfile:
|
65
|
+
To install Reportable for Rails 3.x, add it to your application's Gemfile:
|
84
66
|
|
85
67
|
gem 'reportable', :require => 'saulabs/reportable'
|
86
68
|
|
@@ -109,7 +91,7 @@ Plans
|
|
109
91
|
Authors
|
110
92
|
-------
|
111
93
|
|
112
|
-
© 2008-
|
94
|
+
© 2008-2012 Marco Otte-Witte (<http://simplabs.com>) and Martin Kavalar (<http://www.sauspiel.de>)
|
113
95
|
|
114
96
|
Released under the MIT license
|
115
97
|
|
data/Rakefile
CHANGED
@@ -1,37 +1,18 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
)
|
17
|
-
readme(File.join(File.dirname(__FILE__), 'templates', 'NOTES'))
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
else
|
23
|
-
|
24
|
-
class ReportableJqueryFlotAssetsGenerator < Rails::Generator::Base
|
25
|
-
|
26
|
-
def manifest
|
27
|
-
record do |m|
|
28
|
-
m.directory('public/javascripts')
|
29
|
-
m.file('jquery.flot.min.js', 'public/javascripts/jquery.flot.min.js')
|
30
|
-
m.file('excanvas.min.js', 'public/javascripts/excanvas.min.js')
|
31
|
-
m.readme('NOTES')
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
1
|
+
class ReportableJqueryFlotAssetsGenerator < Rails::Generators::Base
|
2
|
+
|
3
|
+
include Rails::Generators::Actions
|
4
|
+
|
5
|
+
def create_jquery_flot_file
|
6
|
+
empty_directory('public/javascripts')
|
7
|
+
copy_file(
|
8
|
+
File.join(File.dirname(__FILE__), 'templates', 'jquery.flot.min.js'),
|
9
|
+
'public/javascripts/jquery.flot.min.js'
|
10
|
+
)
|
11
|
+
copy_file(
|
12
|
+
File.join(File.dirname(__FILE__), 'templates', 'excanvas.min.js'),
|
13
|
+
'public/javascripts/excanvas.min.js'
|
14
|
+
)
|
15
|
+
readme(File.join(File.dirname(__FILE__), 'templates', 'NOTES'))
|
35
16
|
end
|
36
17
|
|
37
18
|
end
|
@@ -1,40 +1,20 @@
|
|
1
|
-
|
1
|
+
class ReportableMigrationGenerator < Rails::Generators::Base
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
include Rails::Generators::Migration
|
6
|
-
|
7
|
-
def create_migration
|
8
|
-
migration_template(
|
9
|
-
File.join(File.dirname(__FILE__), 'templates', 'migration.rb'),
|
10
|
-
'db/migrate/create_reportable_cache.rb'
|
11
|
-
)
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.next_migration_number(dirname)
|
15
|
-
if ActiveRecord::Base.timestamped_migrations
|
16
|
-
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
17
|
-
else
|
18
|
-
"%.3d" % (current_migration_number(dirname) + 1)
|
19
|
-
end
|
20
|
-
end
|
3
|
+
include Rails::Generators::Migration
|
21
4
|
|
5
|
+
def create_migration
|
6
|
+
migration_template(
|
7
|
+
File.join(File.dirname(__FILE__), 'templates', 'migration.rb'),
|
8
|
+
'db/migrate/create_reportable_cache.rb'
|
9
|
+
)
|
22
10
|
end
|
23
11
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
record do |m|
|
30
|
-
m.migration_template('migration.rb', 'db/migrate')
|
31
|
-
end
|
12
|
+
def self.next_migration_number(dirname)
|
13
|
+
if ActiveRecord::Base.timestamped_migrations
|
14
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
15
|
+
else
|
16
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
32
17
|
end
|
33
|
-
|
34
|
-
def file_name
|
35
|
-
'create_reportable_cache'
|
36
|
-
end
|
37
|
-
|
38
18
|
end
|
39
19
|
|
40
20
|
end
|
@@ -1,42 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
)
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
)
|
21
|
-
readme(File.join(File.dirname(__FILE__), 'templates', 'NOTES'))
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
else
|
27
|
-
|
28
|
-
class ReportableRaphaelAssetsGenerator < Rails::Generator::Base
|
29
|
-
|
30
|
-
def manifest
|
31
|
-
record do |m|
|
32
|
-
m.directory('public/javascripts')
|
33
|
-
m.file('raphael.min.js', 'public/javascripts/raphael.min.js')
|
34
|
-
m.file('g.raphael.min.js', 'public/javascripts/g.raphael.min.js')
|
35
|
-
m.file('g.line.min.js', 'public/javascripts/g.line.min.js')
|
36
|
-
m.readme('NOTES')
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
1
|
+
class ReportableRaphaelAssetsGenerator < Rails::Generators::Base
|
2
|
+
|
3
|
+
include Rails::Generators::Actions
|
4
|
+
|
5
|
+
def create_raphael_file
|
6
|
+
empty_directory('public/javascripts')
|
7
|
+
copy_file(
|
8
|
+
File.join(File.dirname(__FILE__), 'templates', 'raphael.min.js'),
|
9
|
+
'public/javascripts/raphael.min.js'
|
10
|
+
)
|
11
|
+
copy_file(
|
12
|
+
File.join(File.dirname(__FILE__), 'templates', 'g.raphael.min.js'),
|
13
|
+
'public/javascripts/g.raphael.min.js'
|
14
|
+
)
|
15
|
+
copy_file(
|
16
|
+
File.join(File.dirname(__FILE__), 'templates', 'g.line.min.js'),
|
17
|
+
'public/javascripts/g.line.min.js'
|
18
|
+
)
|
19
|
+
readme(File.join(File.dirname(__FILE__), 'templates', 'NOTES'))
|
40
20
|
end
|
41
21
|
|
42
22
|
end
|
data/lib/saulabs/reportable.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
|
1
2
|
require 'saulabs/reportable/report'
|
2
3
|
require 'saulabs/reportable/cumulated_report'
|
4
|
+
require 'saulabs/reportable/railtie'
|
3
5
|
|
4
6
|
module Saulabs
|
5
7
|
|
@@ -9,10 +11,6 @@ module Saulabs
|
|
9
11
|
#
|
10
12
|
module RailsAdapter
|
11
13
|
|
12
|
-
IS_RAILS3 = defined?(Rails) && Rails::VERSION::MAJOR >= 3
|
13
|
-
|
14
|
-
require 'saulabs/reportable/railtie' if IS_RAILS3
|
15
|
-
|
16
14
|
# Extends the {Saulabs::Reportable::ClassMethods#reportable} method into +base+.
|
17
15
|
#
|
18
16
|
def self.included(base)
|
@@ -25,7 +25,7 @@ module Saulabs
|
|
25
25
|
first_reporting_period = ReportingPeriod.first(options[:grouping], options[:limit], options[:end_date])
|
26
26
|
acc = initial_cumulative_value(first_reporting_period.date_time, options)
|
27
27
|
result = []
|
28
|
-
data.each do |element|
|
28
|
+
data.to_a.each do |element|
|
29
29
|
acc += element[1].to_f
|
30
30
|
result << [element[0], acc]
|
31
31
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'saulabs/reportable'
|
2
|
+
require 'saulabs/reportable/report_tag_helper'
|
2
3
|
require 'rails'
|
3
4
|
|
4
5
|
module Saulabs
|
@@ -10,7 +11,17 @@ module Saulabs
|
|
10
11
|
GEM_ROOT = File.join(File.dirname(__FILE__), '..', '..', '..')
|
11
12
|
|
12
13
|
initializer 'saulabs.reportable.initialization' do
|
13
|
-
|
14
|
+
ActiveSupport.on_load :active_record do
|
15
|
+
ActiveRecord::Base.class_eval do
|
16
|
+
include Saulabs::Reportable::RailsAdapter
|
17
|
+
end
|
18
|
+
end
|
19
|
+
ActiveSupport.on_load :action_view do
|
20
|
+
ActionView::Base.class_eval do
|
21
|
+
include Saulabs::Reportable::ReportTagHelper
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
14
25
|
end
|
15
26
|
|
16
27
|
generators do
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'saulabs/reportable/reporting_period'
|
2
2
|
require 'saulabs/reportable/result_set'
|
3
|
+
require 'active_record'
|
3
4
|
|
4
5
|
module Saulabs
|
5
6
|
|
@@ -10,7 +11,7 @@ module Saulabs
|
|
10
11
|
#
|
11
12
|
class ReportCache < ActiveRecord::Base
|
12
13
|
|
13
|
-
|
14
|
+
self.table_name = :reportable_cache
|
14
15
|
|
15
16
|
validates_presence_of :model_name
|
16
17
|
validates_presence_of :report_name
|
@@ -63,7 +64,7 @@ module Saulabs
|
|
63
64
|
# @option options [DateTime, Boolean] :end_date (false)
|
64
65
|
# when specified, the report will only include data for the +:limit+ reporting periods until this date.
|
65
66
|
#
|
66
|
-
# @return [
|
67
|
+
# @return [ResultSet<Array<DateTime, Float>>]
|
67
68
|
# the result of the report as pairs of {DateTime}s and {Float}s
|
68
69
|
#
|
69
70
|
def self.process(report, options, &block)
|
@@ -110,13 +111,24 @@ module Saulabs
|
|
110
111
|
:report_name => report.name.to_s,
|
111
112
|
:grouping => grouping.identifier.to_s,
|
112
113
|
:aggregation => report.aggregation.to_s,
|
113
|
-
:conditions => conditions
|
114
|
+
:conditions => serialize_conditions(conditions),
|
114
115
|
:reporting_period => reporting_period.date_time,
|
115
116
|
:value => value
|
116
117
|
)
|
117
118
|
end
|
118
119
|
|
120
|
+
def self.serialize_conditions(conditions)
|
121
|
+
if conditions.is_a?(Array) && conditions.any?
|
122
|
+
conditions.join
|
123
|
+
elsif conditions.is_a?(Hash) && conditions.any?
|
124
|
+
conditions.map.sort{|x,y|x.to_s<=>y.to_s}.flatten.join
|
125
|
+
else
|
126
|
+
conditions.empty? ? '' : conditions.to_s
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
119
130
|
def self.read_cached_data(report, options)
|
131
|
+
options[:conditions] ||= []
|
120
132
|
conditions = [
|
121
133
|
%w(model_name report_name grouping aggregation conditions).map do |column_name|
|
122
134
|
"#{self.connection.quote_column_name(column_name)} = ?"
|
@@ -125,7 +137,7 @@ module Saulabs
|
|
125
137
|
report.name.to_s,
|
126
138
|
options[:grouping].identifier.to_s,
|
127
139
|
report.aggregation.to_s,
|
128
|
-
options[:conditions]
|
140
|
+
serialize_conditions(options[:conditions])
|
129
141
|
]
|
130
142
|
first_reporting_period = get_first_reporting_period(options)
|
131
143
|
last_reporting_period = get_last_reporting_period(options)
|
@@ -37,7 +37,7 @@ module Saulabs
|
|
37
37
|
#
|
38
38
|
def google_report_tag(data, options = {})
|
39
39
|
options.reverse_merge!(Config.google_options)
|
40
|
-
data = data.collect { |d| d[1] }
|
40
|
+
data = data.to_a.collect { |d| d[1] }
|
41
41
|
labels = ''
|
42
42
|
unless options[:labels].empty?
|
43
43
|
chxr = {}
|
@@ -93,8 +93,8 @@ module Saulabs
|
|
93
93
|
var graph = Raphael('#{options[:dom_id]}');
|
94
94
|
graph.g.linechart(
|
95
95
|
-10, 4, #{options[:width]}, #{options[:height]},
|
96
|
-
#{(0..data.size).to_a.to_json},
|
97
|
-
#{data.map { |d|
|
96
|
+
#{(0..data.to_a.size).to_a.to_json},
|
97
|
+
#{data.to_a.map { |d| d[1].send(:eval, options[:format]) }.to_json},
|
98
98
|
#{raphael_options.to_json}
|
99
99
|
).hover(function() {
|
100
100
|
this.disc = graph.g.disc(this.x, this.y, 3).attr({fill: "#{options[:hover_fill_color]}", stroke: '#{options[:hover_line_color]}' }).insertBefore(this);
|
@@ -146,7 +146,7 @@ module Saulabs
|
|
146
146
|
%Q{<div id="#{options[:dom_id]}" style="width:#{options[:width]}px;height:#{options[:height]}px;"></div>
|
147
147
|
<script type="text\/javascript" charset="utf-8">
|
148
148
|
$(function() {
|
149
|
-
var set = #{data.map{|d| d[1] }.to_json},
|
149
|
+
var set = #{data.to_a.map{|d| d[1] }.to_json},
|
150
150
|
data = [];
|
151
151
|
for (var i = 0; i < set.length; i++) {
|
152
152
|
data.push([i, set[i]]);
|
@@ -70,7 +70,8 @@ module Saulabs
|
|
70
70
|
# the reporting period for the {Saulabs::Reportable::Grouping} as parsed from the db string
|
71
71
|
#
|
72
72
|
def self.from_db_string(grouping, db_string)
|
73
|
-
|
73
|
+
return self.new(grouping, db_string) if db_string.is_a?(Date)
|
74
|
+
parts = grouping.date_parts_from_db_string(db_string.to_s)
|
74
75
|
case grouping.identifier
|
75
76
|
when :hour
|
76
77
|
self.new(grouping, DateTime.new(parts[0], parts[1], parts[2], parts[3], 0, 0))
|
@@ -8,7 +8,7 @@ module Saulabs
|
|
8
8
|
# the name of the model and the report the result set
|
9
9
|
# was generated from.
|
10
10
|
#
|
11
|
-
class ResultSet
|
11
|
+
class ResultSet
|
12
12
|
|
13
13
|
# the name of the model the result set is based on
|
14
14
|
#
|
@@ -18,6 +18,12 @@ module Saulabs
|
|
18
18
|
#
|
19
19
|
attr_reader :report_name
|
20
20
|
|
21
|
+
# array representation of the result
|
22
|
+
#
|
23
|
+
def to_a
|
24
|
+
@results
|
25
|
+
end
|
26
|
+
|
21
27
|
# Initializes a new result set.
|
22
28
|
#
|
23
29
|
# @param [Array] array
|
@@ -28,7 +34,7 @@ module Saulabs
|
|
28
34
|
# the name of the report the result is based on
|
29
35
|
#
|
30
36
|
def initialize(array, model_name, report_name)
|
31
|
-
|
37
|
+
@results = array
|
32
38
|
@model_name = model_name
|
33
39
|
@report_name = report_name.to_s
|
34
40
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__),
|
1
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))),'spec_helper')
|
2
2
|
|
3
3
|
describe Saulabs::Reportable::ReportCache do
|
4
4
|
|
@@ -214,7 +214,7 @@ describe Saulabs::Reportable::ReportCache do
|
|
214
214
|
@report.name.to_s,
|
215
215
|
@report.options[:grouping].identifier.to_s,
|
216
216
|
@report.aggregation.to_s,
|
217
|
-
|
217
|
+
'',
|
218
218
|
Saulabs::Reportable::ReportingPeriod.first(@report.options[:grouping], 10).date_time
|
219
219
|
],
|
220
220
|
:limit => 10,
|
@@ -235,7 +235,7 @@ describe Saulabs::Reportable::ReportCache do
|
|
235
235
|
@report.name.to_s,
|
236
236
|
@report.options[:grouping].identifier.to_s,
|
237
237
|
@report.aggregation.to_s,
|
238
|
-
|
238
|
+
'',
|
239
239
|
Saulabs::Reportable::ReportingPeriod.first(@report.options[:grouping], 9).date_time,
|
240
240
|
Saulabs::Reportable::ReportingPeriod.new(@report.options[:grouping], end_date).date_time
|
241
241
|
],
|
@@ -248,8 +248,7 @@ describe Saulabs::Reportable::ReportCache do
|
|
248
248
|
|
249
249
|
it "should read existing data from the cache for the correct grouping if one other than the report's default grouping is specified" do
|
250
250
|
grouping = Saulabs::Reportable::Grouping.new(:month)
|
251
|
-
Saulabs::Reportable::ReportCache.should_receive(:
|
252
|
-
:all,
|
251
|
+
Saulabs::Reportable::ReportCache.should_receive(:all).once.with(
|
253
252
|
:conditions => [
|
254
253
|
%w(model_name report_name grouping aggregation conditions).map do |column_name|
|
255
254
|
"#{Saulabs::Reportable::ReportCache.connection.quote_column_name(column_name)} = ?"
|
@@ -258,7 +257,7 @@ describe Saulabs::Reportable::ReportCache do
|
|
258
257
|
@report.name.to_s,
|
259
258
|
grouping.identifier.to_s,
|
260
259
|
@report.aggregation.to_s,
|
261
|
-
|
260
|
+
'',
|
262
261
|
Saulabs::Reportable::ReportingPeriod.first(grouping, 10).date_time
|
263
262
|
],
|
264
263
|
:limit => 10,
|
@@ -276,6 +275,25 @@ describe Saulabs::Reportable::ReportCache do
|
|
276
275
|
end
|
277
276
|
end
|
278
277
|
end
|
278
|
+
|
279
|
+
describe '.serialize_conditions' do
|
280
|
+
|
281
|
+
it 'should serialize empty conditions correctly' do
|
282
|
+
result = Saulabs::Reportable::ReportCache.send(:serialize_conditions, [])
|
283
|
+
result.should eql('')
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'should serialize a conditions array correctly' do
|
287
|
+
result = Saulabs::Reportable::ReportCache.send(:serialize_conditions, ['active = ? AND gender = ?', true, 'male'])
|
288
|
+
result.should eql('active = ? AND gender = ?truemale')
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'should serialize a conditions hash correctly' do
|
292
|
+
result = Saulabs::Reportable::ReportCache.send(:serialize_conditions, { :gender => 'male', :active => true })
|
293
|
+
result.should eql('activetruegendermale')
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
279
297
|
|
280
298
|
describe '.prepare_result' do
|
281
299
|
|
@@ -320,7 +338,7 @@ describe Saulabs::Reportable::ReportCache do
|
|
320
338
|
end
|
321
339
|
|
322
340
|
it 'should save the created Saulabs::Reportable::ReportCache' do
|
323
|
-
@cached.should_receive(:save!)
|
341
|
+
@cached.should_receive(:save!)
|
324
342
|
|
325
343
|
Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
|
326
344
|
end
|
@@ -328,16 +346,17 @@ describe Saulabs::Reportable::ReportCache do
|
|
328
346
|
it 'should return an array of arrays of Dates and Floats' do
|
329
347
|
result = Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
|
330
348
|
|
331
|
-
result.should be_kind_of(
|
332
|
-
result
|
333
|
-
result[0]
|
334
|
-
result[0][
|
349
|
+
result.should be_kind_of(Saulabs::Reportable::ResultSet)
|
350
|
+
result.to_a.should be_kind_of(Array)
|
351
|
+
result.to_a[0].should be_kind_of(Array)
|
352
|
+
result.to_a[0][0].should be_kind_of(Date)
|
353
|
+
result.to_a[0][1].should be_kind_of(Float)
|
335
354
|
end
|
336
355
|
|
337
356
|
describe 'with :live_data = false' do
|
338
357
|
|
339
358
|
before do
|
340
|
-
@result = Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
|
359
|
+
@result = Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options).to_a
|
341
360
|
end
|
342
361
|
|
343
362
|
it 'should return an array of length :limit' do
|
@@ -354,7 +373,7 @@ describe Saulabs::Reportable::ReportCache do
|
|
354
373
|
|
355
374
|
before do
|
356
375
|
options = @report.options.merge(:live_data => true)
|
357
|
-
@result = Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, options)
|
376
|
+
@result = Saulabs::Reportable::ReportCache.send(:prepare_result, @new_data, [], @report, options).to_a
|
358
377
|
end
|
359
378
|
|
360
379
|
it 'should return an array of length (:limit + 1)' do
|
data/spec/classes/report_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__),
|
1
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))),'spec_helper')
|
2
2
|
|
3
3
|
describe Saulabs::Reportable::Report do
|
4
4
|
|
@@ -56,13 +56,13 @@ describe Saulabs::Reportable::Report do
|
|
56
56
|
it 'should return an array of the same length as the specified limit when :live_data is false' do
|
57
57
|
@report = Saulabs::Reportable::Report.new(User, :cumulated_registrations, :limit => 10, :live_data => false)
|
58
58
|
|
59
|
-
@report.run.length.should == 10
|
59
|
+
@report.run.to_a.length.should == 10
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'should return an array of the same length as the specified limit + 1 when :live_data is true' do
|
63
63
|
@report = Saulabs::Reportable::Report.new(User, :cumulated_registrations, :limit => 10, :live_data => true)
|
64
64
|
|
65
|
-
@report.run.length.should == 11
|
65
|
+
@report.run.to_a.length.should == 11
|
66
66
|
end
|
67
67
|
|
68
68
|
for grouping in [:hour, :day, :week, :month] do
|
@@ -98,7 +98,7 @@ describe Saulabs::Reportable::Report do
|
|
98
98
|
:limit => 10,
|
99
99
|
:end_date => @end_date
|
100
100
|
)
|
101
|
-
@result = @report.run
|
101
|
+
@result = @report.run.to_a
|
102
102
|
end
|
103
103
|
|
104
104
|
it "should start with the reporting period (end_date - limit.#{grouping.to_s})" do
|
@@ -127,7 +127,7 @@ describe Saulabs::Reportable::Report do
|
|
127
127
|
:limit => 10,
|
128
128
|
:live_data => live_data
|
129
129
|
)
|
130
|
-
@result = @report.run
|
130
|
+
@result = @report.run.to_a
|
131
131
|
end
|
132
132
|
|
133
133
|
it "should be an array starting reporting period (Time.now - limit.#{grouping.to_s})" do
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__),
|
1
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))),'spec_helper')
|
2
2
|
|
3
3
|
describe Saulabs::Reportable::ReportingPeriod do
|
4
4
|
|
@@ -138,6 +138,16 @@ describe Saulabs::Reportable::ReportingPeriod do
|
|
138
138
|
|
139
139
|
Saulabs::Reportable::ReportingPeriod.from_db_string(grouping, '').date_time.should == Date.new(2008, 1, 1)
|
140
140
|
end
|
141
|
+
|
142
|
+
it "should return a reporting period with the correct date when a Date object is passed" do
|
143
|
+
grouping = Saulabs::Reportable::Grouping.new(:day)
|
144
|
+
Saulabs::Reportable::ReportingPeriod.from_db_string(grouping, Date.new(2008, 1, 1)).date_time.should == Date.new(2008, 1, 1)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should return a reporting period with the correct date when a DateTime object is passed" do
|
148
|
+
grouping = Saulabs::Reportable::Grouping.new(:hour)
|
149
|
+
Saulabs::Reportable::ReportingPeriod.from_db_string(grouping, DateTime.new(2008, 1, 1, 12, 0, 0)).date_time.should == DateTime.new(2008, 1, 1, 12, 0, 0)
|
150
|
+
end
|
141
151
|
|
142
152
|
end
|
143
153
|
|
data/spec/db/database.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
sqlite3:
|
2
2
|
adapter: sqlite3
|
3
|
-
database:
|
3
|
+
database: ":memory:"
|
4
4
|
mysql:
|
5
5
|
adapter: mysql
|
6
6
|
database: reportable_test
|
@@ -12,4 +12,4 @@ postgresql:
|
|
12
12
|
database: reportable_test
|
13
13
|
username: reportable
|
14
14
|
password: reportable
|
15
|
-
host: localhost
|
15
|
+
host: localhost
|
@@ -1,7 +1,17 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__),
|
1
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))),'spec_helper')
|
2
2
|
|
3
3
|
describe Saulabs::Reportable do
|
4
|
+
|
5
|
+
ActiveRecord::Base.class_eval do
|
6
|
+
include Saulabs::Reportable::RailsAdapter
|
7
|
+
end
|
8
|
+
|
9
|
+
class User < ActiveRecord::Base
|
10
|
+
reportable :registrations, :limit => 10
|
11
|
+
end
|
4
12
|
|
13
|
+
class SpecialUser < User; end
|
14
|
+
|
5
15
|
before(:all) do
|
6
16
|
User.create!(:login => 'test 1', :created_at => Time.now - 1.days, :profile_visits => 1)
|
7
17
|
User.create!(:login => 'test 2', :created_at => Time.now - 2.days, :profile_visits => 2)
|
@@ -59,10 +69,3 @@ describe Saulabs::Reportable do
|
|
59
69
|
|
60
70
|
end
|
61
71
|
|
62
|
-
class User < ActiveRecord::Base
|
63
|
-
|
64
|
-
reportable :registrations, :limit => 10
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
class SpecialUser < User; end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__),
|
1
|
+
require File.join(File.dirname(File.dirname(File.expand_path(__FILE__))),'spec_helper')
|
2
|
+
|
3
|
+
require 'reportable/report_tag_helper'
|
2
4
|
|
3
5
|
describe Saulabs::Reportable::ReportTagHelper do
|
4
6
|
|
@@ -30,6 +32,10 @@ describe Saulabs::Reportable::ReportTagHelper do
|
|
30
32
|
@helper.raphael_report_tag(data_set).should =~ /^<div id="#{data_set.model_name.downcase}_#{data_set.report_name}".*<\/div>/
|
31
33
|
@helper.raphael_report_tag(data_set).should =~ /^<div id="#{data_set.model_name.downcase}_#{data_set.report_name}1".*<\/div>/
|
32
34
|
end
|
35
|
+
|
36
|
+
it 'should include the data [1,3]' do
|
37
|
+
@helper.raphael_report_tag(data_set).should =~ /\[1,3\]/
|
38
|
+
end
|
33
39
|
|
34
40
|
end
|
35
41
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,19 +1,39 @@
|
|
1
1
|
ENV['RAILS_ENV'] = 'test'
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
-
require 'bundler'
|
5
|
-
|
6
|
-
|
7
|
-
require
|
8
|
-
|
9
|
-
class User < ActiveRecord::Base; end
|
10
|
-
|
11
|
-
class YieldMatchException < Exception; end
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'active_record'
|
6
|
+
require 'active_record/version'
|
7
|
+
require 'active_support'
|
12
8
|
|
13
9
|
begin
|
14
10
|
require 'ruby-debug'
|
15
|
-
Debugger.start
|
16
|
-
Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
|
11
|
+
# Debugger.start
|
12
|
+
# Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
|
17
13
|
rescue LoadError
|
18
14
|
# ruby-debug wasn't available so neither can the debugging be
|
19
|
-
end
|
15
|
+
end
|
16
|
+
|
17
|
+
ROOT = Pathname(File.expand_path(File.join(File.dirname(__FILE__), '..')))
|
18
|
+
|
19
|
+
$LOAD_PATH << File.join(ROOT, 'lib')
|
20
|
+
$LOAD_PATH << File.join(ROOT, 'lib/saulabs')
|
21
|
+
|
22
|
+
require File.join(ROOT, 'lib', 'saulabs', 'reportable.rb')
|
23
|
+
|
24
|
+
# Rails::Initializer.run(:set_load_path)
|
25
|
+
# Rails::Initializer.run(:set_autoload_paths)
|
26
|
+
# Rails::Initializer.run(:initialize_time_zone) do |config|
|
27
|
+
# config.time_zone = 'Pacific Time (US & Canada)'
|
28
|
+
# end
|
29
|
+
|
30
|
+
FileUtils.mkdir_p File.join(File.dirname(__FILE__), 'log')
|
31
|
+
ActiveRecord::Base.logger = ActiveSupport::BufferedLogger.new(File.dirname(__FILE__) + "/log/spec.log")
|
32
|
+
|
33
|
+
databases = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'db', 'database.yml')))
|
34
|
+
ActiveRecord::Base.establish_connection(databases[ENV['DB'] || 'sqlite3'])
|
35
|
+
load(File.join(File.dirname(__FILE__), 'db', 'schema.rb'))
|
36
|
+
|
37
|
+
class User < ActiveRecord::Base; end
|
38
|
+
|
39
|
+
class YieldMatchException < Exception; end
|
metadata
CHANGED
@@ -1,79 +1,60 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: reportable
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 1
|
9
|
-
- 2
|
10
|
-
version: 1.1.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Marco Otte-Witte
|
14
9
|
- Martin Kavalar
|
15
10
|
autorequire:
|
16
11
|
bindir: bin
|
17
12
|
cert_chain: []
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
dependencies:
|
22
|
-
- !ruby/object:Gem::Dependency
|
13
|
+
date: 2012-02-14 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
23
16
|
name: activerecord
|
24
|
-
|
25
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
17
|
+
requirement: &70168900389180 !ruby/object:Gem::Requirement
|
26
18
|
none: false
|
27
|
-
requirements:
|
28
|
-
- -
|
29
|
-
- !ruby/object:Gem::Version
|
30
|
-
|
31
|
-
segments:
|
32
|
-
- 2
|
33
|
-
- 0
|
34
|
-
- 0
|
35
|
-
version: 2.0.0
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '3.0'
|
36
23
|
type: :runtime
|
37
|
-
version_requirements: *id001
|
38
|
-
- !ruby/object:Gem::Dependency
|
39
|
-
name: activesupport
|
40
24
|
prerelease: false
|
41
|
-
|
25
|
+
version_requirements: *70168900389180
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: activesupport
|
28
|
+
requirement: &70168900388200 !ruby/object:Gem::Requirement
|
42
29
|
none: false
|
43
|
-
requirements:
|
44
|
-
- -
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
|
47
|
-
segments:
|
48
|
-
- 2
|
49
|
-
- 0
|
50
|
-
- 0
|
51
|
-
version: 2.0.0
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.0
|
52
34
|
type: :runtime
|
53
|
-
|
54
|
-
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70168900388200
|
37
|
+
description: Reportable allows for easy report generation from ActiveRecord models
|
38
|
+
by the addition of the reportable method.
|
55
39
|
email: reportable@saulabs.com
|
56
40
|
executables: []
|
57
|
-
|
58
41
|
extensions: []
|
59
|
-
|
60
42
|
extra_rdoc_files: []
|
61
|
-
|
62
|
-
files:
|
43
|
+
files:
|
63
44
|
- README.md
|
64
45
|
- HISTORY.md
|
65
46
|
- Rakefile
|
66
47
|
- MIT-LICENSE
|
67
48
|
- generators/reportable_jquery_flot_assets/reportable_jquery_flot_assets_generator.rb
|
68
|
-
- generators/reportable_jquery_flot_assets/templates/NOTES
|
69
49
|
- generators/reportable_jquery_flot_assets/templates/excanvas.min.js
|
70
50
|
- generators/reportable_jquery_flot_assets/templates/jquery.flot.min.js
|
51
|
+
- generators/reportable_jquery_flot_assets/templates/NOTES
|
71
52
|
- generators/reportable_migration/reportable_migration_generator.rb
|
72
53
|
- generators/reportable_migration/templates/migration.rb
|
73
54
|
- generators/reportable_raphael_assets/reportable_raphael_assets_generator.rb
|
74
|
-
- generators/reportable_raphael_assets/templates/NOTES
|
75
55
|
- generators/reportable_raphael_assets/templates/g.line.min.js
|
76
56
|
- generators/reportable_raphael_assets/templates/g.raphael.min.js
|
57
|
+
- generators/reportable_raphael_assets/templates/NOTES
|
77
58
|
- generators/reportable_raphael_assets/templates/raphael.min.js
|
78
59
|
- lib/saulabs/reportable/config.rb
|
79
60
|
- lib/saulabs/reportable/cumulated_report.rb
|
@@ -85,8 +66,6 @@ files:
|
|
85
66
|
- lib/saulabs/reportable/reporting_period.rb
|
86
67
|
- lib/saulabs/reportable/result_set.rb
|
87
68
|
- lib/saulabs/reportable.rb
|
88
|
-
- rails/init.rb
|
89
|
-
- spec/boot.rb
|
90
69
|
- spec/classes/cumulated_report_spec.rb
|
91
70
|
- spec/classes/grouping_spec.rb
|
92
71
|
- spec/classes/report_cache_spec.rb
|
@@ -98,39 +77,29 @@ files:
|
|
98
77
|
- spec/spec_helper.rb
|
99
78
|
- spec/db/database.yml
|
100
79
|
- spec/spec.opts
|
101
|
-
has_rdoc: true
|
102
80
|
homepage: http://github.com/saulabs/reportable
|
103
81
|
licenses: []
|
104
|
-
|
105
82
|
post_install_message:
|
106
83
|
rdoc_options: []
|
107
|
-
|
108
|
-
require_paths:
|
84
|
+
require_paths:
|
109
85
|
- lib
|
110
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
87
|
none: false
|
112
|
-
requirements:
|
113
|
-
- -
|
114
|
-
- !ruby/object:Gem::Version
|
115
|
-
|
116
|
-
|
117
|
-
- 0
|
118
|
-
version: "0"
|
119
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ! '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
93
|
none: false
|
121
|
-
requirements:
|
122
|
-
- -
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
|
125
|
-
segments:
|
126
|
-
- 0
|
127
|
-
version: "0"
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
128
98
|
requirements: []
|
129
|
-
|
130
99
|
rubyforge_project:
|
131
|
-
rubygems_version: 1.
|
100
|
+
rubygems_version: 1.8.11
|
132
101
|
signing_key:
|
133
|
-
specification_version:
|
102
|
+
specification_version: 3
|
134
103
|
summary: Easy report generation for Ruby on Rails
|
135
104
|
test_files: []
|
136
|
-
|
105
|
+
has_rdoc: false
|
data/rails/init.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'action_view'
|
2
|
-
require 'saulabs/reportable'
|
3
|
-
require 'saulabs/reportable/report_tag_helper'
|
4
|
-
|
5
|
-
ActiveRecord::Base.class_eval do
|
6
|
-
include Saulabs::Reportable::RailsAdapter
|
7
|
-
end
|
8
|
-
|
9
|
-
ActionView::Base.class_eval do
|
10
|
-
include Saulabs::Reportable::ReportTagHelper
|
11
|
-
end
|
data/spec/boot.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
plugin_root = File.join(File.dirname(__FILE__), '..')
|
2
|
-
|
3
|
-
$:.unshift "#{plugin_root}/lib"
|
4
|
-
|
5
|
-
Bundler.require
|
6
|
-
require 'initializer'
|
7
|
-
|
8
|
-
RAILS_ROOT = File.expand_path(File.dirname(__FILE__) + '/../') unless defined?(RAILS_ROOT)
|
9
|
-
Rails::Initializer.run(:set_load_path)
|
10
|
-
Rails::Initializer.run(:set_autoload_paths)
|
11
|
-
Rails::Initializer.run(:initialize_time_zone) do |config|
|
12
|
-
config.time_zone = 'Pacific Time (US & Canada)'
|
13
|
-
end
|
14
|
-
|
15
|
-
require File.join(File.dirname(__FILE__), '..', 'rails', 'init.rb')
|
16
|
-
|
17
|
-
FileUtils.mkdir_p File.join(File.dirname(__FILE__), 'log')
|
18
|
-
ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), 'log', 'spec.log'))
|
19
|
-
|
20
|
-
databases = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'db', 'database.yml')))
|
21
|
-
ActiveRecord::Base.establish_connection(databases[ENV['DB'] || 'sqlite3'])
|
22
|
-
load(File.join(File.dirname(__FILE__), 'db', 'schema.rb'))
|