reportable 1.1.2 → 1.2.0
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/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'))
|