included run limit in cache identifier (closes #3) - reportable - Fork of reportable required by WarVox, from hdm/reportable.
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
(DIR) commit 063ae7ebfb466b15d8fdb0347f9c4eaeff7775b2
(DIR) parent a8fd0e703fd9b424cc69125c89722d85664bb5da
(HTM) Author: Marco Otte-Witte <marco.otte-witte@simplabs.com>
Date: Wed, 29 Apr 2009 15:00:55 +0200
included run limit in cache identifier (closes #3)
Diffstat:
M generators/reports_as_sparkline_mi… | 15 +++++++++------
M lib/simplabs/reports_as_sparkline/… | 52 ++++++++++---------------------
M spec/classes/report_cache_spec.rb | 48 +++++++++++++++----------------
M spec/classes/report_spec.rb | 22 ++++++++++++++++++++++
M spec/db/schema.rb | 11 +++++++----
5 files changed, 77 insertions(+), 71 deletions(-)
---
(DIR) diff --git a/generators/reports_as_sparkline_migration/templates/migration.erb b/generators/reports_as_sparkline_migration/templates/migration.erb
@@ -8,6 +8,7 @@ class <%= class_name %> < ActiveRecord::Migration
t.string :aggregation, :null => false
t.float :value, :null => false, :default => 0
t.datetime :reporting_period, :null => false
+ t.integer :run_limit, :null => false
t.timestamps
end
@@ -16,20 +17,22 @@ class <%= class_name %> < ActiveRecord::Migration
:model_name,
:report_name,
:grouping,
- :aggregation
- ], :name => :name_model_grouping_agregation
+ :aggregation,
+ :run_limit
+ ], :name => :name_model_grouping_agregation_run_limit
add_index :reports_as_sparkline_cache, [
:model_name,
:report_name,
:grouping,
:aggregation,
- :reporting_period
- ], :unique => true, :name => :name_model_grouping_aggregation_period
+ :reporting_period,
+ :run_limit
+ ], :unique => true, :name => :name_model_grouping_aggregation_period_run_limit
end
def self.down
- remove_index :reports_as_sparkline_cache, :name => :name_model_grouping_agregation
- remove_index :reports_as_sparkline_cache, :name => :name_model_grouping_aggregation_period
+ remove_index :reports_as_sparkline_cache, :name => :name_model_grouping_agregation_run_limit
+ remove_index :reports_as_sparkline_cache, :name => :name_model_grouping_aggregation_period_run_limit
drop_table :reports_as_sparkline_cache
end
(DIR) diff --git a/lib/simplabs/reports_as_sparkline/report_cache.rb b/lib/simplabs/reports_as_sparkline/report_cache.rb
@@ -12,61 +12,39 @@ module Simplabs #:nodoc:
cached_data = []
first_reporting_period = ReportingPeriod.first(options[:grouping], options[:limit], options[:end_date])
last_reporting_period = options[:end_date] ? ReportingPeriod.new(options[:grouping], options[:end_date]) : nil
+
if cache
cached_data = find_cached_data(report, options, first_reporting_period, last_reporting_period)
first_cached_reporting_period = cached_data.empty? ? nil : ReportingPeriod.new(options[:grouping], cached_data.first.reporting_period)
last_cached_reporting_period = cached_data.empty? ? nil : ReportingPeriod.new(options[:grouping], cached_data.last.reporting_period)
end
- new_after_cache_data = if !options[:live_data] && last_cached_reporting_period == ReportingPeriod.new(options[:grouping]).previous
+
+ new_data = if !options[:live_data] && last_cached_reporting_period == ReportingPeriod.new(options[:grouping]).previous
[]
else
end_date = options[:live_data] ? nil : last_reporting_period && last_reporting_period.date_time
yield((last_cached_reporting_period.next rescue first_reporting_period).date_time, end_date)
end
- new_before_cache_data = if cached_data.empty? || first_cached_reporting_period.date_time == first_reporting_period.date_time
- []
- else
- yield(first_reporting_period.date_time, first_cached_reporting_period.date_time)
- end
- prepare_result(new_before_cache_data, new_after_cache_data, cached_data, report, options, cache)
+
+ prepare_result(new_data, cached_data, report, options, cache)
end
end
private
- def self.prepare_result(new_before_cache_data, new_after_cache_data, cached_data, report, options, cache = true)
- cache_map_proc = lambda { |data| [ReportingPeriod.from_db_string(options[:grouping], data[0]), data[1]] }
-
- new_after_cache_data = new_after_cache_data.map &cache_map_proc
- new_before_cache_data = new_before_cache_data.map &cache_map_proc
+ def self.prepare_result(new_data, cached_data, report, options, cache = true)
+ new_data = new_data.map { |data| [ReportingPeriod.from_db_string(options[:grouping], data[0]), data[1]] }
result = cached_data.map { |cached| [cached.reporting_period, cached.value] }
-
- first_reporting_period = ReportingPeriod.first(options[:grouping], options[:limit], options[:end_date])
last_reporting_period = ReportingPeriod.new(options[:grouping], options[:end_date])
- first_cached_reporting_period = cached_data.empty? ? nil : ReportingPeriod.new(options[:grouping], cached_data.first.reporting_period)
- last_cached_reporting_period = cached_data.empty? ? nil : ReportingPeriod.new(options[:grouping], cached_data.last.reporting_period)
-
- if first_cached_reporting_period
- reporting_period = first_reporting_period
- while reporting_period < first_cached_reporting_period
- cached = build_cached_data(report, options[:grouping], reporting_period, find_value(new_before_cache_data, reporting_period))
- cached.save! if cache
- result.insert(0, [reporting_period.date_time, cached.value])
- reporting_period = reporting_period.next
- end
- end
-
- reporting_period = cached_data.empty? ? first_reporting_period : last_cached_reporting_period.next
-
+ reporting_period = cached_data.empty? ? ReportingPeriod.first(options[:grouping], options[:limit], options[:end_date]) : ReportingPeriod.new(options[:grouping], cached_data.last.reporting_period).next
while reporting_period < last_reporting_period
- cached = build_cached_data(report, options[:grouping], reporting_period, find_value(new_after_cache_data, reporting_period))
+ cached = build_cached_data(report, options[:grouping], options[:limit], reporting_period, find_value(new_data, reporting_period))
cached.save! if cache
result << [reporting_period.date_time, cached.value]
reporting_period = reporting_period.next
end
-
if options[:live_data]
- result << [last_reporting_period.date_time, find_value(new_after_cache_data, last_reporting_period)]
+ result << [last_reporting_period.date_time, find_value(new_data, last_reporting_period)]
end
result
end
@@ -76,24 +54,26 @@ module Simplabs #:nodoc:
data ? data[1] : 0.0
end
- def self.build_cached_data(report, grouping, reporting_period, value)
+ def self.build_cached_data(report, grouping, limit, reporting_period, value)
self.new(
:model_name => report.klass.to_s,
:report_name => report.name.to_s,
:grouping => grouping.identifier.to_s,
:aggregation => report.aggregation.to_s,
:reporting_period => reporting_period.date_time,
- :value => value
+ :value => value,
+ :run_limit => limit
)
end
def self.find_cached_data(report, options, first_reporting_period, last_reporting_period)
conditions = [
- 'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ?',
+ 'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ? AND run_limit = ?',
report.klass.to_s,
report.name.to_s,
options[:grouping].identifier.to_s,
- report.aggregation.to_s
+ report.aggregation.to_s,
+ options[:limit]
]
if last_reporting_period
conditions.first << ' AND reporting_period BETWEEN ? AND ?'
(DIR) diff --git a/spec/classes/report_cache_spec.rb b/spec/classes/report_cache_spec.rb
@@ -37,7 +37,7 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
}.should raise_error(YieldMatchException)
end
- it 'should yield the reporting period after the last one in the cache, and before the first one in the cache if data was read from cache' do
+ it 'should yield the reporting period after the last one in the cache if data was read from cache' do
reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(
@report.options[:grouping],
Time.now - 3.send(@report.options[:grouping].identifier)
@@ -46,15 +46,11 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
cached.stub!(:reporting_period).and_return(reporting_period.date_time)
Simplabs::ReportsAsSparkline::ReportCache.stub!(:find).and_return([cached])
- expected_dates = [[reporting_period.next.date_time, nil], [reporting_period.offset(-7).date_time, reporting_period.date_time]]
- yield_count = 0
Simplabs::ReportsAsSparkline::ReportCache.process(@report, @options) do |begin_at, end_at|
- [begin_at, end_at].should == expected_dates[yield_count]
- yield_count += 1
+ begin_at.should == reporting_period.next.date_time
+ end_at.should == nil
[]
end
-
- yield_count.should == 2
end
end
@@ -76,7 +72,7 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
}.should raise_error(YieldMatchException)
end
- it 'should yield the reporting period after the last one in the cache, and before the first one in the cache if data was read from cache' do
+ it 'should yield the reporting period after the last one in the cache if data was read from cache' do
reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(
@report.options[:grouping],
Time.now - 3.send(@report.options[:grouping].identifier)
@@ -85,15 +81,11 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
cached.stub!(:reporting_period).and_return(reporting_period.date_time)
Simplabs::ReportsAsSparkline::ReportCache.stub!(:find).and_return([cached])
- expected_dates = [[reporting_period.next.date_time, nil], [reporting_period.offset(-7).date_time, reporting_period.date_time]]
- yield_count = 0
Simplabs::ReportsAsSparkline::ReportCache.process(@report, @report.options) do |begin_at, end_at|
- [begin_at, end_at].should == expected_dates[yield_count]
- yield_count += 1
+ begin_at.should == reporting_period.next.date_time
+ end_at.should == nil
[]
end
-
- yield_count.should == 2
end
end
@@ -102,11 +94,12 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
Simplabs::ReportsAsSparkline::ReportCache.should_receive(:find).once.with(
:all,
:conditions => [
- 'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ? AND reporting_period >= ?',
+ 'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ? AND run_limit = ? AND reporting_period >= ?',
@report.klass.to_s,
@report.name.to_s,
@report.options[:grouping].identifier.to_s,
@report.aggregation.to_s,
+ 10,
Simplabs::ReportsAsSparkline::ReportingPeriod.first(@report.options[:grouping], 10).date_time
],
:limit => 10,
@@ -121,11 +114,12 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
Simplabs::ReportsAsSparkline::ReportCache.should_receive(:find).once.with(
:all,
:conditions => [
- 'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ? AND reporting_period BETWEEN ? AND ?',
+ 'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ? AND run_limit = ? AND reporting_period BETWEEN ? AND ?',
@report.klass.to_s,
@report.name.to_s,
@report.options[:grouping].identifier.to_s,
@report.aggregation.to_s,
+ 10,
Simplabs::ReportsAsSparkline::ReportingPeriod.first(@report.options[:grouping], 10).date_time,
Simplabs::ReportsAsSparkline::ReportingPeriod.new(@report.options[:grouping], end_date).date_time
],
@@ -141,11 +135,12 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
Simplabs::ReportsAsSparkline::ReportCache.should_receive(:find).once.with(
:all,
:conditions => [
- 'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ? AND reporting_period >= ?',
+ 'model_name = ? AND report_name = ? AND grouping = ? AND aggregation = ? AND run_limit = ? AND reporting_period >= ?',
@report.klass.to_s,
@report.name.to_s,
grouping.identifier.to_s,
@report.aggregation.to_s,
+ 10,
Simplabs::ReportsAsSparkline::ReportingPeriod.first(grouping, 10).date_time
],
:limit => 10,
@@ -187,7 +182,7 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
before do
@current_reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(@report.options[:grouping])
- @new_after_cache_data = [[@current_reporting_period.previous.date_time, 1.0]]
+ @new_data = [[@current_reporting_period.previous.date_time, 1.0]]
Simplabs::ReportsAsSparkline::ReportingPeriod.stub!(:from_db_string).and_return(@current_reporting_period.previous)
@cached = Simplabs::ReportsAsSparkline::ReportCache.new
@cached.stub!(:save!)
@@ -198,38 +193,41 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
Simplabs::ReportsAsSparkline::ReportCache.should_receive(:build_cached_data).exactly(10).times.with(
@report,
@report.options[:grouping],
+ 10,
anything(),
0.0
).and_return(@cached)
- Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, [], [], [], @report, @report.options)
+ Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, [], [], @report, @report.options)
end
it 'should create a new Simplabs::ReportsAsSparkline::ReportCache with the correct value if new data has been read' do
Simplabs::ReportsAsSparkline::ReportCache.should_receive(:build_cached_data).exactly(9).times.with(
@report,
@report.options[:grouping],
+ 10,
anything(),
0.0
).and_return(@cached)
Simplabs::ReportsAsSparkline::ReportCache.should_receive(:build_cached_data).once.with(
@report,
@report.options[:grouping],
+ 10,
@current_reporting_period.previous,
1.0
).and_return(@cached)
- Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, [], @new_after_cache_data, [], @report, @report.options)
+ Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
end
it 'should save the created Simplabs::ReportsAsSparkline::ReportCache' do
@cached.should_receive(:save!).once
- Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, [], @new_after_cache_data, [], @report, @report.options)
+ Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
end
it 'should return an array of arrays of Dates and Floats' do
- result = Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, [], @new_after_cache_data, [], @report, @report.options, true)
+ result = Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options, true)
result.should be_kind_of(Array)
result[0].should be_kind_of(Array)
@@ -240,7 +238,7 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
describe 'with :live_data = false' do
before do
- @result = Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, [], @new_after_cache_data, [], @report, @report.options, true)
+ @result = Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options, true)
end
it 'should return an array of length :limit' do
@@ -257,7 +255,7 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
before do
options = @report.options.merge(:live_data => true)
- @result = Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, [], @new_after_cache_data, [], @report, options, true)
+ @result = Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, options, true)
end
it 'should return an array of length (:limit + 1)' do
@@ -275,7 +273,7 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
it 'should not save the created Simplabs::ReportsAsSparkline::ReportCache' do
@cached.should_not_receive(:save!)
- Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, [], @new_after_cache_data, [], @report, @report.options, false)
+ Simplabs::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options, false)
end
end
(DIR) diff --git a/spec/classes/report_spec.rb b/spec/classes/report_spec.rb
@@ -228,6 +228,28 @@ describe Simplabs::ReportsAsSparkline::Report do
result[6][1].should == 0.0
end
+ it 'should return correct results when run twice with different limits' do
+ @report = Simplabs::ReportsAsSparkline::Report.new(User, :registrations,
+ :aggregation => :count,
+ :grouping => grouping,
+ :limit => 10,
+ :live_data => live_data
+ )
+ result = @report.run(:limit => 2).to_a
+
+ result[2][1].should == 1.0 if live_data
+ result[1][1].should == 1.0
+ result[0][1].should == 0.0
+
+ result = @report.run(:limit => 10).to_a
+
+ result[10][1].should == 1.0 if live_data
+ result[9][1].should == 1.0
+ result[8][1].should == 0.0
+ result[7][1].should == 2.0
+ result[6][1].should == 0.0
+ end
+
end
after(:all) do
(DIR) diff --git a/spec/db/schema.rb b/spec/db/schema.rb
@@ -15,6 +15,7 @@ ActiveRecord::Schema.define(:version => 1) do
t.string :aggregation, :null => false
t.float :value, :null => false, :default => 0
t.datetime :reporting_period, :null => false
+ t.integer :run_limit, :null => false
t.timestamps
end
@@ -22,14 +23,16 @@ ActiveRecord::Schema.define(:version => 1) do
:model_name,
:report_name,
:grouping,
- :aggregation
- ], :name => :name_model_grouping_agregation
+ :aggregation,
+ :run_limit
+ ], :name => :name_model_grouping_agregation_run_limit
add_index :reports_as_sparkline_cache, [
:model_name,
:report_name,
:grouping,
:aggregation,
- :reporting_period
- ], :unique => true, :name => :name_model_grouping_aggregation_period
+ :reporting_period,
+ :run_limit
+ ], :unique => true, :name => :name_model_grouping_aggregation_period_run_limit
end