Introduction
Introduction Statistics Contact Development Disclaimer Help
Added :end_date option. - reportable - Fork of reportable required by WarVox, f…
Log
Files
Refs
README
---
commit 5dd3e6e1a3c3851b6fe2b7c0d20abc65425ed268
parent 52fc6a795cb9b10fce03b8283a6d461389871e02
Author: Myron Marston <[email protected]>
Date: Fri, 3 Apr 2009 23:55:03 +0800
Added :end_date option.
Signed-off-by: Marco Otte-Witte <[email protected]>
Diffstat:
M lib/kvlr/reports_as_sparkline/repo… | 27 +++++++++++++++++++--------
M lib/kvlr/reports_as_sparkline/repo… | 46 ++++++++++++++++++++-------…
M lib/kvlr/reports_as_sparkline/repo… | 8 ++++----
M spec/classes/report_cache_spec.rb | 32 +++++++++++++++++++++++++++--…
M spec/classes/report_spec.rb | 93 +++++++++++++++++++++++------…
M spec/classes/reporting_period_spec… | 6 ++++++
6 files changed, 157 insertions(+), 55 deletions(-)
---
diff --git a/lib/kvlr/reports_as_sparkline/report.rb b/lib/kvlr/reports_as_spar…
@@ -20,6 +20,7 @@ module Kvlr #:nodoc:
# * <tt>:limit</tt> - The number of periods to get (see :grouping)
# * <tt>:conditions</tt> - Conditions like in ActiveRecord::Base#find; o…
# * <tt>:live_data</tt> - Specified whether data for the current reporti…
+ # * <tt>:end_date</tt> - When specified, the report will be for the peri…
def initialize(klass, name, options = {})
ensure_valid_options(options)
@klass = klass
@@ -31,7 +32,8 @@ module Kvlr #:nodoc:
:limit => options[:limit] || 100,
:conditions => options[:conditions] || [],
:grouping => Grouping.new(options[:grouping] || :day),
- :live_data => options[:live_data] || false
+ :live_data => options[:live_data] || false,
+ :end_date => options[:end_date]
}
@options.merge!(options)
@options.freeze
@@ -44,20 +46,22 @@ module Kvlr #:nodoc:
# * <tt>:conditions</tt> - Conditions like in ActiveRecord::Base#find; o…
# * <tt>:grouping</tt> - The period records are grouped on (:hour, :day,…
# * <tt>:live_data</tt> - Specified whether data for the current reporti…
+ # * <tt>:end_date</tt> - When specified, the report will be for the peri…
def run(options = {})
+ options = options.dup
ensure_valid_options(options, :run)
custom_conditions = options.key?(:conditions)
options.reverse_merge!(@options)
options[:grouping] = Grouping.new(options[:grouping]) unless options[:…
- ReportCache.process(self, options, !custom_conditions) do |begin_at|
- read_data(begin_at, options)
+ ReportCache.process(self, options, !custom_conditions) do |begin_at, e…
+ read_data(begin_at, end_at, options)
end
end
private
- def read_data(begin_at, options)
- conditions = setup_conditions(begin_at, options[:conditions])
+ def read_data(begin_at, end_at, options)
+ conditions = setup_conditions(begin_at, end_at, options[:conditions])
@klass.send(@aggregation,
@value_column,
:conditions => conditions,
@@ -66,7 +70,7 @@ module Kvlr #:nodoc:
)
end
- def setup_conditions(begin_at, custom_conditions = [])
+ def setup_conditions(begin_at, end_at, custom_conditions = [])
conditions = ['']
if custom_conditions.is_a?(Hash)
conditions = [custom_conditions.map do |k, v|
@@ -83,19 +87,26 @@ module Kvlr #:nodoc:
end
conditions[0] += "#{(conditions[0].blank? ? '' : ' AND ') + @date_co…
conditions << begin_at
+
+ if end_at
+ conditions[0].sub!(/>= \?\z/, 'BETWEEN ? AND ?')
+ conditions << end_at
+ end
+
+ conditions
end
def ensure_valid_options(options, context = :initialize)
case context
when :initialize
options.each_key do |k|
- raise ArgumentError.new("Invalid option #{k}") unless [:limit,…
+ raise ArgumentError.new("Invalid option #{k}") unless [:limit,…
end
raise ArgumentError.new("Invalid aggregation #{options[:aggregat…
raise ArgumentError.new('The name of the column holding the valu…
when :run
options.each_key do |k|
- raise ArgumentError.new("Invalid option #{k}") unless [:limit,…
+ raise ArgumentError.new("Invalid option #{k}") unless [:limit,…
end
end
raise ArgumentError.new("Invalid grouping #{options[:grouping]}") if…
diff --git a/lib/kvlr/reports_as_sparkline/report_cache.rb b/lib/kvlr/reports_a…
@@ -8,16 +8,23 @@ module Kvlr #:nodoc:
raise ArgumentError.new('A block must be given') unless block_given?
self.transaction do
cached_data = []
- first_reporting_period = ReportingPeriod.first(options[:grouping], o…
+ first_reporting_period = ReportingPeriod.first(options[:grouping], o…
+ last_reporting_period = options[:end_date] ? ReportingPeriod.new(opt…
+
if cache
- cached_data = find_cached_data(report, options, first_reporting_pe…
+ cached_data = find_cached_data(report, options, first_reporting_pe…
+ first_cached_reporting_period = cached_data.empty? ? nil : Reporti…
last_cached_reporting_period = cached_data.empty? ? nil : Reportin…
end
+
+ # Get any missing data that comes after our cached data...
new_data = if !options[:live_data] && last_cached_reporting_period =…
[]
else
- yield((last_cached_reporting_period.next rescue first_reporting_pe…
+ end_date = options[:live_data] ? nil : last_reporting_period && la…
+ yield((last_cached_reporting_period.next rescue first_reporting_pe…
end
+
prepare_result(new_data, cached_data, report, options, cache)
end
end
@@ -27,16 +34,16 @@ module Kvlr #:nodoc:
def self.prepare_result(new_data, cached_data, report, options, cache …
new_data = new_data.map { |data| [ReportingPeriod.from_db_string(opt…
result = cached_data.map { |cached| [cached.reporting_period, cached…
- current_reporting_period = ReportingPeriod.new(options[:grouping])
- reporting_period = cached_data.empty? ? ReportingPeriod.first(option…
- while reporting_period < current_reporting_period
+ last_reporting_period = ReportingPeriod.new(options[:grouping], opti…
+ reporting_period = cached_data.empty? ? ReportingPeriod.first(option…
+ while reporting_period < last_reporting_period
cached = build_cached_data(report, options[:grouping], reporting_p…
cached.save! if cache
result << [reporting_period.date_time, cached.value]
reporting_period = reporting_period.next
end
if options[:live_data]
- result << [current_reporting_period.date_time, find_value(new_data…
+ result << [last_reporting_period.date_time, find_value(new_data, l…
end
result
end
@@ -57,17 +64,24 @@ module Kvlr #:nodoc:
)
end
- def self.find_cached_data(report, options, first_reporting_period)
+ def self.find_cached_data(report, options, first_reporting_period, las…
+ conditions = [
+ 'model_name = ? AND report_name = ? AND grouping = ? AND aggregati…
+ report.klass.to_s,
+ report.name.to_s,
+ options[:grouping].identifier.to_s,
+ report.aggregation.to_s,
+ first_reporting_period.date_time
+ ]
+
+ if last_reporting_period
+ conditions.first.sub!(/>= \?\z/, 'BETWEEN ? AND ?')
+ conditions << last_reporting_period.date_time
+ end
+
self.find(
:all,
- :conditions => [
- 'model_name = ? AND report_name = ? AND grouping = ? AND aggrega…
- report.klass.to_s,
- report.name.to_s,
- options[:grouping].identifier.to_s,
- report.aggregation.to_s,
- first_reporting_period.date_time
- ],
+ :conditions => conditions,
:limit => options[:limit],
:order => 'reporting_period ASC'
)
diff --git a/lib/kvlr/reports_as_sparkline/reporting_period.rb b/lib/kvlr/repor…
@@ -10,9 +10,9 @@ module Kvlr #:nodoc:
# ==== Parameters
# * <tt>grouping</tt> - The Kvlr::ReportsAsSparkline::Grouping of the re…
# * <tt>date_time</tt> - The DateTime that reporting period is created f…
- def initialize(grouping, date_time = DateTime.now)
+ def initialize(grouping, date_time = nil)
@grouping = grouping
- @date_time = parse_date_time(date_time)
+ @date_time = parse_date_time(date_time || DateTime.now)
end
# Returns the first reporting period for a grouping and a limit; e.g. th…
@@ -20,8 +20,8 @@ module Kvlr #:nodoc:
# ==== Parameters
# * <tt>grouping</tt> - The Kvlr::ReportsAsSparkline::Grouping of the re…
# * <tt>limit</tt> - The number of reporting periods until the first one
- def self.first(grouping, limit)
- self.new(grouping, DateTime.now).offset(-limit)
+ def self.first(grouping, limit, end_date = nil)
+ self.new(grouping, end_date).offset(-limit)
end
def self.from_db_string(grouping, db_string) #:nodoc:
diff --git a/spec/classes/report_cache_spec.rb b/spec/classes/report_cache_spec…
@@ -46,8 +46,9 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
cached.stub!(:reporting_period).and_return(reporting_period.date_time)
Kvlr::ReportsAsSparkline::ReportCache.stub!(:find).and_return([cached])
- Kvlr::ReportsAsSparkline::ReportCache.process(@report, @options) do |b…
+ Kvlr::ReportsAsSparkline::ReportCache.process(@report, @options) do |b…
begin_at.should == reporting_period.next.date_time
+ end_at.should == nil
[]
end
end
@@ -80,8 +81,9 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
cached.stub!(:reporting_period).and_return(reporting_period.date_time)
Kvlr::ReportsAsSparkline::ReportCache.stub!(:find).and_return([cached])
- Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options…
+ Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options…
begin_at.should == reporting_period.next.date_time
+ end_at.should == nil
[]
end
end
@@ -106,6 +108,26 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options) …
end
+ it 'should utilize the end_date in the conditions' do
+ end_date = Time.now
+ Kvlr::ReportsAsSparkline::ReportCache.should_receive(:find).once.with(
+ :all,
+ :conditions => [
+ 'model_name = ? AND report_name = ? AND grouping = ? AND aggregation…
+ @report.klass.to_s,
+ @report.name.to_s,
+ @report.options[:grouping].identifier.to_s,
+ @report.aggregation.to_s,
+ Kvlr::ReportsAsSparkline::ReportingPeriod.first(@report.options[:gro…
+ Kvlr::ReportsAsSparkline::ReportingPeriod.new(@report.options[:group…
+ ],
+ :limit => 10,
+ :order => 'reporting_period ASC'
+ )
+
+ Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options.m…
+ end
+
it "should read existing data from the cache for the correct grouping if o…
grouping = Kvlr::ReportsAsSparkline::Grouping.new(:month)
Kvlr::ReportsAsSparkline::ReportCache.should_receive(:find).once.with(
@@ -135,8 +157,9 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
end
it 'should yield the first reporting period if the cache is empty' do
- Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options) …
+ Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options) …
begin_at.should == Kvlr::ReportsAsSparkline::ReportingPeriod.first(@re…
+ end_at.should == nil
[]
end
end
@@ -150,8 +173,9 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
end
it 'should yield the first reporting period' do
- Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options…
+ Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options…
begin_at.should == Kvlr::ReportsAsSparkline::ReportingPeriod.first(@…
+ end_at.should == nil
[]
end
end
diff --git a/spec/classes/report_spec.rb b/spec/classes/report_spec.rb
@@ -3,6 +3,8 @@ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
describe Kvlr::ReportsAsSparkline::Report do
before do
+ @now = DateTime.now
+ DateTime.stub!(:now).and_return(@now)
@report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations)
end
@@ -19,7 +21,7 @@ describe Kvlr::ReportsAsSparkline::Report do
it 'should process the data with the report cache' do
Kvlr::ReportsAsSparkline::ReportCache.should_receive(:process).once.with(
@report,
- { :limit => 100, :grouping => @report.options[:grouping], :conditions …
+ { :limit => 100, :grouping => @report.options[:grouping], :conditions …
true
)
@@ -29,7 +31,7 @@ describe Kvlr::ReportsAsSparkline::Report do
it 'should process the data with the report cache and specify cache = fals…
Kvlr::ReportsAsSparkline::ReportCache.should_receive(:process).once.with(
@report,
- { :limit => 100, :grouping => @report.options[:grouping], :conditions …
+ { :limit => 100, :grouping => @report.options[:grouping], :conditions …
false
)
@@ -47,7 +49,7 @@ describe Kvlr::ReportsAsSparkline::Report do
Kvlr::ReportsAsSparkline::Grouping.should_receive(:new).once.with(:month…
Kvlr::ReportsAsSparkline::ReportCache.should_receive(:process).once.with(
@report,
- { :limit => 100, :grouping => grouping, :conditions => [], :live_data …
+ { :limit => 100, :grouping => grouping, :conditions => [], :live_data …
true
)
@@ -66,6 +68,44 @@ describe Kvlr::ReportsAsSparkline::Report do
@report.run.length.should == 11
end
+ describe "a month report with a limit of 2" do
+ before(:all) do
+ User.create!(:login => 'test 1', :created_at => Time.now, :p…
+ User.create!(:login => 'test 2', :created_at => Time.now - 1.month, :p…
+ User.create!(:login => 'test 3', :created_at => Time.now - 3.month, :p…
+ User.create!(:login => 'test 4', :created_at => Time.now - 3.month, :p…
+
+ @report2 = Kvlr::ReportsAsSparkline::Report.new(User, :registrations,
+ :grouping => :month,
+ :limit => 2
+ )
+
+ @one_month_ago = Date.new(DateTime.now.year, DateTime.now.month, 1)…
+ @two_months_ago = Date.new(DateTime.now.year, DateTime.now.month, 1)…
+ @three_months_ago = Date.new(DateTime.now.year, DateTime.now.month, 1)…
+ end
+
+ it "should return data for the last two months when there is no end date…
+ @report2.run.should == [[@two_months_ago, 0.0], [@one_month_ago, 1.0]]
+ end
+
+ it "should return data for two months prior to the end date" do
+ @report2.run(:end_date => 1.month.ago).should == [[@three_months_ago, …
+ end
+
+ it "should return data for the two months prior to the end date, and als…
+ @report2.run(:end_date => 1.month.ago, :live_data => true).should == […
+ end
+
+ it "should return data for the two months prior to the end date, and als…
+ # run it once to get from the database...
+ @report2.run(:end_date => 1.month.ago, :live_data => true)
+
+ # and then again from the cache...
+ @report2.run(:end_date => 1.month.ago, :live_data => true).should == […
+ end
+ end
+
for grouping in [:hour, :day, :week, :month] do
describe "for grouping #{grouping.to_s}" do
@@ -316,13 +356,13 @@ describe Kvlr::ReportsAsSparkline::Report do
@report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :ag…
User.should_receive(:count).once.and_return([])
- @report.send(:read_data, Time.now, { :grouping => @report.options[:group…
+ @report.send(:read_data, Time.now, 5.days.from_now, { :grouping => @repo…
end
it 'should setup the conditions' do
@report.should_receive(:setup_conditions).once.and_return([])
- @report.send(:read_data, Time.now, { :grouping => @report.options[:group…
+ @report.send(:read_data, Time.now, 5.days.from_now, { :grouping => @repo…
end
end
@@ -331,53 +371,60 @@ describe Kvlr::ReportsAsSparkline::Report do
before do
@begin_at = Time.now
+ @end_at = 5.days.from_now
+ end
+
+ it 'should return conditions for date_column BETWEEN begin_at and end_at o…
+ @report.send(:setup_conditions, @begin_at, @end_at).should == ['created_…
end
- it 'should return conditions for date_column >= begin_at only when no cust…
- @report.send(:setup_conditions, @begin_at).should == ['created_at >= ?',…
+ it 'should return conditions for date_column >= begin_at when no custom co…
+ @report.send(:setup_conditions, @begin_at, nil).should == ['created_at >…
end
- it 'should return conditions for date_column >= begin_at only when an empt…
- @report.send(:setup_conditions, @begin_at, {}).should == ['created_at >=…
+ it 'should return conditions for date_column BETWEEN begin_at and end_date…
+ @report.send(:setup_conditions, @begin_at, @end_at, {}).should == ['crea…
end
- it 'should return conditions for date_column >= begin_at only when an empt…
- @report.send(:setup_conditions, @begin_at, []).should == ['created_at >=…
+ it 'should return conditions for date_column BETWEEN begin_at and end_date…
+ @report.send(:setup_conditions, @begin_at, @end_at, []).should == ['crea…
end
it 'should correctly include custom conditions if they are specified as a …
custom_conditions = { :first_name => 'first name', :last_name => 'last n…
- conditions = @report.send(:setup_conditions, @begin_at, custom_condition…
+ conditions = @report.send(:setup_conditions, @begin_at, @end_at, custom_…
#cannot check for equality of complete conditions array since hashes are…
conditions[0].should include('first_name = ?')
conditions[0].should include('last_name = ?')
- conditions[0].should include('created_at >= ?')
+ conditions[0].should include('created_at BETWEEN ? AND ?')
conditions.should include('first name')
conditions.should include('last name')
conditions.should include(@begin_at)
+ conditions.should include(@end_at)
end
it 'should correctly translate { :column => nil }' do
- @report.send(:setup_conditions, @begin_at, { :column => nil }).should ==…
+ @report.send(:setup_conditions, @begin_at, @end_at, { :column => nil }).…
end
it 'should correctly translate { :column => [1, 2] }' do
- @report.send(:setup_conditions, @begin_at, { :column => [1, 2] }).should…
+ @report.send(:setup_conditions, @begin_at, @end_at, { :column => [1, 2] …
end
it 'should correctly translate { :column => (1..3) }' do
- @report.send(:setup_conditions, @begin_at, { :column => (1..3) }).should…
+ @report.send(:setup_conditions, @begin_at, @end_at, { :column => (1..3) …
end
it 'should correctly include custom conditions if they are specified as an…
custom_conditions = ['first_name = ? AND last_name = ?', 'first name', '…
- @report.send(:setup_conditions, @begin_at, custom_conditions).should == [
- 'first_name = ? AND last_name = ? AND created_at >= ?',
+ @report.send(:setup_conditions, @begin_at, @end_at, custom_conditions).s…
+ 'first_name = ? AND last_name = ? AND created_at BETWEEN ? AND ?',
'first name',
'last name',
- @begin_at
+ @begin_at,
+ @end_at
]
end
@@ -415,11 +462,11 @@ describe Kvlr::ReportsAsSparkline::Report do
})
}.should_not raise_error(ArgumentError)
end
-
+
it 'should raise an error if an unsupported option is specified' do
lambda { @report.send(:ensure_valid_options, { :invalid => :option }) …
end
-
+
it 'should raise an error if an invalid aggregation is specified' do
lambda { @report.send(:ensure_valid_options, { :aggregation => :invali…
end
@@ -436,13 +483,13 @@ describe Kvlr::ReportsAsSparkline::Report do
lambda { @report.send(:ensure_valid_options, { :limit => 100, :conditi…
}.should_not raise_error(ArgumentError)
end
-
+
it 'should raise an error if an unsupported option is specified' do
lambda { @report.send(:ensure_valid_options, { :aggregation => :sum },…
end
end
-
+
end
end
diff --git a/spec/classes/reporting_period_spec.rb b/spec/classes/reporting_per…
@@ -232,6 +232,12 @@ describe Kvlr::ReportsAsSparkline::ReportingPeriod do
reporting_period.date_time.should == DateTime.new(2008, 12, 8) #the mond…
end
+ it 'should return a reporting period that is offset from the end date by t…
+ date = DateTime.new(2009, 3, 31)
+ reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.first(Kvlr:…
+ reporting_period.date_time.should == DateTime.new(2009, 3, 28)
+ end
+
end
end
You are viewing proxied material from jay.scot. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.