implemented :live_data option) - reportable - Fork of reportable required by WarVox, from hdm/reportable.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 4bdd41ffb940013461b09f647bef8828387a199d
 (DIR) parent a20b9eee3e4f42b987b0452c3b9c2552ff84c732
 (HTM) Author: Marco Otte-Witte <marco.otte-witte@simplabs.com>
       Date:   Tue, 20 Jan 2009 17:40:09 +0100
       
       implemented :live_data option)
       
       Diffstat:
         M lib/kvlr/reports_as_sparkline/repo… |       2 +-
         M lib/kvlr/reports_as_sparkline/repo… |      26 ++++++++++++++++----------
         M lib/kvlr/reports_as_sparkline/repo… |      11 +++++------
         M spec/classes/cumulated_report_spec… |     182 ++++++++++++++++++++-----------
         M spec/classes/report_cache_spec.rb   |     154 ++++++++++++++++++++++---------
         M spec/classes/report_spec.rb         |     192 ++++++++++++++++++++++---------
         M spec/classes/reporting_period_spec… |      16 ++++++++--------
         M spec/other/report_method_spec.rb    |       9 ++++-----
       
       8 files changed, 396 insertions(+), 196 deletions(-)
       ---
 (DIR) diff --git a/lib/kvlr/reports_as_sparkline/report.rb b/lib/kvlr/reports_as_sparkline/report.rb
       @@ -81,7 +81,7 @@ module Kvlr #:nodoc:
                  case context
                    when :initialize
                      options.each_key do |k|
       -                raise ArgumentError.new("Invalid option #{k}") unless [:limit, :aggregation, :grouping, :date_column, :value_column, :conditions].include?(k)
       +                raise ArgumentError.new("Invalid option #{k}") unless [:limit, :aggregation, :grouping, :date_column, :value_column, :conditions, :live_data].include?(k)
                      end
                      raise ArgumentError.new("Invalid aggregation #{options[:aggregation]}") if options[:aggregation] && ![:count, :sum].include?(options[:aggregation])
                      raise ArgumentError.new('The name of the column holding the value to sum has to be specified for aggregation :sum') if options[:aggregation] == :sum && !options.key?(:value_column)
 (DIR) diff --git a/lib/kvlr/reports_as_sparkline/report_cache.rb b/lib/kvlr/reports_as_sparkline/report_cache.rb
       @@ -8,30 +8,36 @@ module Kvlr #:nodoc:
                raise ArgumentError.new('A block must be given') unless block_given?
                self.transaction do
                  cached_data = []
       -          last_reporting_period_to_read = ReportingPeriod.first(options[:grouping], options[:limit])
       +          first_reporting_period = ReportingPeriod.first(options[:grouping], options[:limit])
                  if cache
       -            cached_data = find_cached_data(report, options, last_reporting_period_to_read)
       -            last_reporting_period_to_read = ReportingPeriod.new(options[:grouping], cached_data.last.reporting_period).next unless cached_data.empty?
       +            cached_data = find_cached_data(report, options, first_reporting_period)
       +            last_cached_reporting_period = (ReportingPeriod.new(options[:grouping], cached_data.last.reporting_period.date_time) rescue nil)
                  end
       -          new_data = yield(last_reporting_period_to_read.date_time)
       -          prepare_result(new_data, cached_data, last_reporting_period_to_read, report, options, cache)[0..(options[:limit] - 1)]
       +          new_data = if !options[:live_data] && last_cached_reporting_period == ReportingPeriod.new(options[:grouping]).previous
       +            []
       +          else
       +            yield((last_cached_reporting_period.next rescue first_reporting_period).date_time)
       +          end
       +          prepare_result(new_data, cached_data, report, options, cache)
                end
              end
        
              private
        
       -        def self.prepare_result(new_data, cached_data, last_reporting_period_to_read, report, options, cache = true)
       +        def self.prepare_result(new_data, cached_data, report, options, cache = true)
                  new_data.map! { |data| [ReportingPeriod.from_db_string(options[:grouping], data[0]), data[1]] }
                  result = cached_data.map { |cached| [cached.reporting_period, cached.value] }
                  current_reporting_period = ReportingPeriod.new(options[:grouping])
       -          reporting_period = last_reporting_period_to_read
       +          reporting_period = (cached_data.last.reporting_period.next rescue ReportingPeriod.first(options[:grouping], options[:limit]))
                  while reporting_period < current_reporting_period
                    cached = build_cached_data(report, options[:grouping], 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
       -          result << [current_reporting_period.date_time, find_value(new_data, current_reporting_period)]
       +          if options[:live_data]
       +            result << [current_reporting_period.date_time, find_value(new_data, current_reporting_period)]
       +          end
                  result
                end
        
       @@ -51,7 +57,7 @@ module Kvlr #:nodoc:
                  )
                end
        
       -        def self.find_cached_data(report, options, last_reporting_period_to_read)
       +        def self.find_cached_data(report, options, first_reporting_period)
                  self.find(
                    :all,
                    :conditions => [
       @@ -60,7 +66,7 @@ module Kvlr #:nodoc:
                      report.name.to_s,
                      options[:grouping].identifier.to_s,
                      report.aggregation.to_s,
       -              last_reporting_period_to_read.date_time
       +              first_reporting_period.date_time
                    ],
                    :limit => options[:limit],
                    :order => 'reporting_period ASC'
 (DIR) diff --git a/lib/kvlr/reports_as_sparkline/reporting_period.rb b/lib/kvlr/reports_as_sparkline/reporting_period.rb
       @@ -15,8 +15,7 @@ module Kvlr #:nodoc:
                @date_time = parse_date_time(date_time)
              end
        
       -      # Returns the first reporting period for a grouping and a limit; e.g. the first reporting period for Grouping :day and limit 2 would be Time.now - 1.days
       -      # (since limit is 2, 2 reporting periods are included in the range, that is yesterday and today)
       +      # Returns the first reporting period for a grouping and a limit; e.g. the first reporting period for Grouping :day and limit 2 would be Time.now - 2.days
              #
              # ==== Parameters
              # * <tt>grouping</tt> - The Kvlr::ReportsAsSparkline::Grouping of the reporting period
       @@ -24,13 +23,13 @@ module Kvlr #:nodoc:
              def self.first(grouping, limit)
                return case grouping.identifier
                  when :hour
       -            self.new(grouping, DateTime.now - (limit - 1).hours)
       +            self.new(grouping, DateTime.now - limit.hours)
                  when :day
       -            self.new(grouping, DateTime.now - (limit - 1).days)
       +            self.new(grouping, DateTime.now - limit.days)
                  when :week
       -            self.new(grouping, DateTime.now - (limit - 1).weeks)
       +            self.new(grouping, DateTime.now - limit.weeks)
                  when :month
       -            date = DateTime.now - (limit - 1).months
       +            date = DateTime.now - limit.months
                    self.new(grouping, Date.new(date.year, date.month, 1))
                end
              end
 (DIR) diff --git a/spec/classes/cumulated_report_spec.rb b/spec/classes/cumulated_report_spec.rb
       @@ -14,90 +14,140 @@ describe Kvlr::ReportsAsSparkline::CumulatedReport do
              @report.run
            end
        
       -    it 'should return an array of the same length as the specified limit' do
       -      @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :cumulated_registrations, :limit => 10)
       +    it 'should return an array of the same length as the specified limit when :live_data is false' do
       +      @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :cumulated_registrations, :limit => 10, :live_data => false)
        
              @report.run.length.should == 10
            end
        
       -    for grouping in [:hour, :day, :week, :month] do
       +    it 'should return an array of the same length as the specified limit + 1 when :live_data is true' do
       +      @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :cumulated_registrations, :limit => 10, :live_data => true)
        
       -      describe "for grouping #{grouping.to_s}" do
       +      @report.run.length.should == 11
       +    end
        
       -        before(:all) do
       -          User.create!(:login => 'test 1', :created_at => Time.now - 1.send(grouping), :profile_visits => 1)
       -          User.create!(:login => 'test 2', :created_at => Time.now - 3.send(grouping), :profile_visits => 2)
       -          User.create!(:login => 'test 3', :created_at => Time.now - 3.send(grouping), :profile_visits => 3)
       -        end
       +    for grouping in [:hour, :day, :week, :month] do
        
       -        describe do
       +      describe "for grouping #{grouping.to_s}" do
        
       -          before do
       -            @grouping = Kvlr::ReportsAsSparkline::Grouping.new(grouping)
       -            @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :cumulated_registrations, :grouping => grouping, :limit => 10)
       -            @result = @report.run
       -          end
       +        [true, false].each do |live_data|
       +
       +          describe "with :live_data = #{live_data}" do
       +
       +            before(:all) do
       +              User.create!(:login => 'test 1', :created_at => Time.now - 1.send(grouping), :profile_visits => 1)
       +              User.create!(:login => 'test 2', :created_at => Time.now - 3.send(grouping), :profile_visits => 2)
       +              User.create!(:login => 'test 3', :created_at => Time.now - 3.send(grouping), :profile_visits => 3)
       +            end
       +
       +            describe do
       +
       +              before do
       +                @grouping = Kvlr::ReportsAsSparkline::Grouping.new(grouping)
       +                @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :cumulated_registrations,
       +                  :grouping  => grouping,
       +                  :limit     => 10,
       +                  :live_data => live_data
       +                )
       +                @result = @report.run
       +              end
       +
       +              it "should return an array starting reporting period (Time.now - limit.#{grouping.to_s})" do
       +                @result.first[0].should == Kvlr::ReportsAsSparkline::ReportingPeriod.new(@grouping, Time.now - 10.send(grouping)).date_time
       +              end
       +
       +              if live_data
       +                it "should return data ending with the current reporting period" do
       +                  @result.last[0].should == Kvlr::ReportsAsSparkline::ReportingPeriod.new(@grouping).date_time
       +                end
       +              else
       +                it "should return data ending with the reporting period before the current" do
       +                  @result.last[0].should == Kvlr::ReportsAsSparkline::ReportingPeriod.new(@grouping).previous.date_time
       +                end
       +              end
       +
       +            end
       +
       +            it 'should return correct data for aggregation :count' do
       +              @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations,
       +                :aggregation => :count,
       +                :grouping    => grouping,
       +                :limit       => 10,
       +                :live_data   => live_data
       +              )
       +              result = @report.run
       +
       +              result[10][1].should == 3.0 if live_data
       +              result[9][1].should  == 3.0
       +              result[8][1].should  == 2.0
       +              result[7][1].should  == 2.0
       +              result[6][1].should  == 0.0
       +            end
       +
       +            it 'should return correct data for aggregation :sum' do
       +              @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations,
       +                :aggregation  => :sum,
       +                :grouping     => grouping,
       +                :value_column => :profile_visits,
       +                :limit        => 10,
       +                :live_data    => live_data
       +              )
       +              result = @report.run()
       +
       +              result[10][1].should == 6.0 if live_data
       +              result[9][1].should  == 6.0
       +              result[8][1].should  == 5.0
       +              result[7][1].should  == 5.0
       +              result[6][1].should  == 0.0
       +            end
       +
       +            it 'should return correct data for aggregation :count when custom conditions are specified' do
       +              @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations,
       +                :aggregation => :count,
       +                :grouping    => grouping,
       +                :limit       => 10,
       +                :live_data   => live_data
       +              )
       +              result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']])
       +
       +              result[10][1].should == 2.0 if live_data
       +              result[9][1].should  == 2.0
       +              result[8][1].should  == 1.0
       +              result[7][1].should  == 1.0
       +              result[6][1].should  == 0.0
       +            end
       +
       +            it 'should return correct data for aggregation :sum when custom conditions are specified' do
       +              @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations,
       +                :aggregation  => :sum,
       +                :grouping     => grouping,
       +                :value_column => :profile_visits,
       +                :limit        => 10,
       +                :live_data    => live_data
       +              )
       +              result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']])
       +
       +              result[10][1].should == 3.0 if live_data
       +              result[9][1].should  == 3.0
       +              result[8][1].should  == 2.0
       +              result[7][1].should  == 2.0
       +              result[6][1].should  == 0.0
       +            end
        
       -          it "should return an array starting reporting period (Time.now - (limit - 1).#{grouping.to_s})" do
       -            @result.first[0].should == Kvlr::ReportsAsSparkline::ReportingPeriod.new(@grouping, Time.now - 9.send(grouping)).date_time
                  end
        
       -          it "should return data ending with with the current reporting period" do
       -            @result.last[0].should == Kvlr::ReportsAsSparkline::ReportingPeriod.new(@grouping).date_time
       +          after(:all) do
       +            User.destroy_all
                  end
        
                end
        
       -        it 'should return correct data for aggregation :count' do
       -          @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations, :aggregation => :count, :grouping => grouping, :limit => 10)
       -          result = @report.run
       -
       -          result[9][1].should == 3.0
       -          result[8][1].should == 3.0
       -          result[7][1].should == 2.0
       -          result[6][1].should == 2.0
       -        end
       -
       -        it 'should return correct data for aggregation :sum' do
       -          @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations, :aggregation => :sum, :grouping => grouping, :value_column => :profile_visits, :limit => 10)
       -          result = @report.run()
       -
       -          result[9][1].should == 6.0
       -          result[8][1].should == 6.0
       -          result[7][1].should == 5.0
       -          result[6][1].should == 5.0
       -        end
       -
       -        it 'should return correct data for aggregation :count when custom conditions are specified' do
       -          @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations, :aggregation => :count, :grouping => grouping, :limit => 10)
       -          result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']])
       -
       -          result[9][1].should == 2.0
       -          result[8][1].should == 2.0
       -          result[7][1].should == 1.0
       -          result[6][1].should == 1.0
       -        end
       -
       -        it 'should return correct data for aggregation :sum when custom conditions are specified' do
       -          @report = Kvlr::ReportsAsSparkline::CumulatedReport.new(User, :registrations, :aggregation => :sum, :grouping => grouping, :value_column => :profile_visits, :limit => 10)
       -          result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']])
       -
       -          result[9][1].should == 3.0
       -          result[8][1].should == 3.0
       -          result[7][1].should == 2.0
       -          result[6][1].should == 2.0
       -        end
       -
       -        after(:all) do
       -          User.destroy_all
       -        end
       -
              end
        
       -      after(:each) do
       -        Kvlr::ReportsAsSparkline::ReportCache.destroy_all
       -      end
       +    end
        
       +    after(:each) do
       +      Kvlr::ReportsAsSparkline::ReportCache.destroy_all
            end
        
          end
 (DIR) diff --git a/spec/classes/report_cache_spec.rb b/spec/classes/report_cache_spec.rb
       @@ -25,10 +25,67 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
              Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options) {}
            end
        
       -    it 'should yield to the given block' do
       -      lambda {
       -        Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options) { raise YieldMatchException.new }
       -      }.should raise_error(YieldMatchException)
       +    describe 'with :live_data = true' do
       +
       +      before do
       +        @options = @report.options.merge(:live_data => true)
       +      end
       +
       +      it 'should yield to the given block' do
       +        lambda {
       +          Kvlr::ReportsAsSparkline::ReportCache.process(@report, @options) { raise YieldMatchException.new }
       +        }.should raise_error(YieldMatchException)
       +      end
       +
       +      it 'should yield the reporting period after the last one in the cache if data was read from cache' do
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(
       +          @report.options[:grouping],
       +          Time.now - 3.send(@report.options[:grouping].identifier)
       +        )
       +        cached = Kvlr::ReportsAsSparkline::ReportCache.new
       +        cached.stub!(:reporting_period).and_return(reporting_period)
       +        Kvlr::ReportsAsSparkline::ReportCache.stub!(:find).and_return([cached])
       +
       +        Kvlr::ReportsAsSparkline::ReportCache.process(@report, @options) do |begin_at|
       +          begin_at.should == reporting_period.next.date_time
       +          []
       +        end
       +      end
       +
       +    end
       +
       +    describe 'with :live_data = false' do
       +
       +      it 'should not yield to the block if data for the reporting period before the current one has been found in the cache' do
       +        cached = Kvlr::ReportsAsSparkline::ReportCache.new
       +        cached.stub!(:reporting_period).and_return(Kvlr::ReportsAsSparkline::ReportingPeriod.new(@report.options[:grouping]).previous)
       +        Kvlr::ReportsAsSparkline::ReportCache.stub!(:find).and_return([cached])
       +        lambda {
       +          Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options) { raise YieldMatchException.new }
       +        }.should_not raise_error(YieldMatchException)
       +      end
       +
       +      it 'should yield to the block if no data for the reporting period before the current one has been found in the cache' do
       +        lambda {
       +          Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options) { raise YieldMatchException.new }
       +        }.should raise_error(YieldMatchException)
       +      end
       +
       +      it 'should yield the reporting period after the last one in the cache if data was read from cache' do
       +        reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(
       +          @report.options[:grouping],
       +          Time.now - 3.send(@report.options[:grouping].identifier)
       +        )
       +        cached = Kvlr::ReportsAsSparkline::ReportCache.new
       +        cached.stub!(:reporting_period).and_return(reporting_period)
       +        Kvlr::ReportsAsSparkline::ReportCache.stub!(:find).and_return([cached])
       +
       +        Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options) do |begin_at|
       +          begin_at.should == reporting_period.next.date_time
       +          []
       +        end
       +      end
       +
            end
        
            it 'should read existing data from the cache' do
       @@ -72,8 +129,7 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
              new_data = []
              cached_data = []
              Kvlr::ReportsAsSparkline::ReportCache.stub!(:find).and_return(cached_data)
       -      last_reporting_period_to_read = Kvlr::ReportsAsSparkline::ReportingPeriod.first(@report.options[:grouping], 10)
       -      Kvlr::ReportsAsSparkline::ReportCache.should_receive(:prepare_result).once.with(new_data, cached_data, last_reporting_period_to_read, @report, @report.options, true)
       +      Kvlr::ReportsAsSparkline::ReportCache.should_receive(:prepare_result).once.with(new_data, cached_data, @report, @report.options, true)
        
              Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options) { new_data }
            end
       @@ -85,24 +141,6 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
              end
            end
        
       -    it 'should yield the reporting period after the last one in the cache if the cache is not empty' do
       -      reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(@report.options[:grouping])
       -      cached = Kvlr::ReportsAsSparkline::ReportCache.new({
       -        :model_name       => @report.klass,
       -        :report_name      => @report.name,
       -        :grouping         => @report.options[:grouping].identifier.to_s,
       -        :aggregation      => @report.aggregation.to_s,
       -        :value            => 1,
       -        :reporting_period => reporting_period.date_time
       -      })
       -      Kvlr::ReportsAsSparkline::ReportCache.stub!(:find).and_return([cached])
       -
       -      Kvlr::ReportsAsSparkline::ReportCache.process(@report, @report.options) do |begin_at|
       -        begin_at.should == reporting_period.next.date_time
       -        []
       -      end
       -    end
       -
            describe 'with cache = false' do
        
              it 'should not read any data from cache' do
       @@ -125,9 +163,9 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
          describe '.prepare_result' do
        
            before do
       -      @last_reporting_period_to_read = Kvlr::ReportsAsSparkline::ReportingPeriod.first(@report.options[:grouping], 10)
       -      @new_data = [[@last_reporting_period_to_read.date_time, 1.0]]
       -      Kvlr::ReportsAsSparkline::ReportingPeriod.stub!(:from_db_string).and_return(@last_reporting_period_to_read)
       +      @current_reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.new(@report.options[:grouping])
       +      @new_data = [[@current_reporting_period.previous.date_time, 1.0]]
       +      Kvlr::ReportsAsSparkline::ReportingPeriod.stub!(:from_db_string).and_return(@current_reporting_period.previous)
              @cached = Kvlr::ReportsAsSparkline::ReportCache.new
              @cached.stub!(:save!)
              Kvlr::ReportsAsSparkline::ReportCache.stub!(:build_cached_data).and_return(@cached)
       @@ -136,22 +174,22 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
            it 'should convert the date strings from the newly read data to reporting periods' do
              Kvlr::ReportsAsSparkline::ReportingPeriod.should_receive(:from_db_string).once.with(@report.options[:grouping], @new_data[0][0]).and_return(Kvlr::ReportsAsSparkline::ReportingPeriod.new(@report.options[:grouping]))
        
       -      Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @last_reporting_period_to_read, @report, @report.options)
       +      Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
            end
        
       -    it 'should create (:limit - 1) instances of Kvlr::ReportsAsSparkline::ReportCache with value 0.0 if no new data has been read and nothing was cached' do
       -      Kvlr::ReportsAsSparkline::ReportCache.should_receive(:build_cached_data).exactly(9).times.with(
       +    it 'should create :limit instances of Kvlr::ReportsAsSparkline::ReportCache with value 0.0 if no new data has been read and nothing was cached' do
       +      Kvlr::ReportsAsSparkline::ReportCache.should_receive(:build_cached_data).exactly(10).times.with(
                @report,
                @report.options[:grouping],
                anything(),
                0.0
              ).and_return(@cached)
        
       -      Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, [], [], @last_reporting_period_to_read, @report, @report.options)
       +      Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, [], [], @report, @report.options)
            end
        
            it 'should create a new Kvlr::ReportsAsSparkline::ReportCache with the correct value if new data has been read' do
       -      Kvlr::ReportsAsSparkline::ReportCache.should_receive(:build_cached_data).exactly(8).times.with(
       +      Kvlr::ReportsAsSparkline::ReportCache.should_receive(:build_cached_data).exactly(9).times.with(
                @report,
                @report.options[:grouping],
                anything(),
       @@ -160,21 +198,21 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
              Kvlr::ReportsAsSparkline::ReportCache.should_receive(:build_cached_data).once.with(
                @report,
                @report.options[:grouping],
       -        @last_reporting_period_to_read,
       +        @current_reporting_period.previous,
                1.0
              ).and_return(@cached)
        
       -      Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @last_reporting_period_to_read, @report, @report.options)
       +      Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
            end
        
       -    it 'should save the created Kvlr::ReportsAsSparkline::ReportCache if no_cache is not specified' do
       +    it 'should save the created Kvlr::ReportsAsSparkline::ReportCache' do
              @cached.should_receive(:save!).once
        
       -      Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @last_reporting_period_to_read, @report, @report.options)
       +      Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options)
            end
        
            it 'should return an array of arrays of Dates and Floats' do
       -      result = Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @last_reporting_period_to_read, @report, @report.options, true)
       +      result = Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options, true)
        
              result.should be_kind_of(Array)
              result[0].should be_kind_of(Array)
       @@ -182,19 +220,45 @@ describe Kvlr::ReportsAsSparkline::ReportCache do
              result[0][1].should be_kind_of(Float)
            end
        
       -    describe 'with cache = false' do
       +    describe 'with :live_data = false' do
        
       -      it 'should not save the created Kvlr::ReportsAsSparkline::ReportCache' do
       -        @cached.should_not_receive(:save!)
       +      before do
       +        @result = Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, @report.options, true)
       +      end
       +
       +      it 'should return an array of length :limit' do
       +        @result.length.should == 10
       +      end
       +
       +      it 'should not include an entry for the current reporting period' do
       +        @result.find { |row| row[0] == @current_reporting_period.date_time }.should be_nil
       +      end
       +
       +    end
       +
       +    describe 'with :live_data = true' do
       +
       +      before do
       +        options = @report.options.merge(:live_data => true)
       +        @result = Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @report, options, true)
       +      end
       +
       +      it 'should return an array of length (:limit + 1)' do
       +        @result.length.should == 11
       +      end
        
       -        Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [], @last_reporting_period_to_read, @report, @report.options, false)
       +      it 'should include an entry for the current reporting period' do
       +        @result.find { |row| row[0] == @current_reporting_period.date_time }.should_not be_nil
              end
        
       -      it 'should not update the last cached record if new data has been read for the last reporting period to read' do
       -        Kvlr::ReportsAsSparkline::ReportingPeriod.stub!(:from_db_string).and_return(@last_reporting_period_to_read)
       -        @cached.should_not_receive(:update_attributes!)
       +    end
       +
       +    describe 'with cache = false' do
       +
       +      it 'should not save the created Kvlr::ReportsAsSparkline::ReportCache' do
       +        @cached.should_not_receive(:save!)
        
       -        Kvlr::ReportsAsSparkline::ReportCache.send(:prepare_result, @new_data, [@cached], @last_reporting_period_to_read, @report, @report.options, false)
       +        Kvlr::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
       @@ -54,86 +54,167 @@ describe Kvlr::ReportsAsSparkline::Report do
              @report.run(:grouping => :month)
            end
        
       +    it 'should return an array of the same length as the specified limit when :live_data is false' do
       +      @report = Kvlr::ReportsAsSparkline::Report.new(User, :cumulated_registrations, :limit => 10, :live_data => false)
       +
       +      @report.run.length.should == 10
       +    end
       +
       +    it 'should return an array of the same length as the specified limit + 1 when :live_data is true' do
       +      @report = Kvlr::ReportsAsSparkline::Report.new(User, :cumulated_registrations, :limit => 10, :live_data => true)
       +
       +      @report.run.length.should == 11
       +    end
       +
            for grouping in [:hour, :day, :week, :month] do
        
              describe "for grouping #{grouping.to_s}" do
        
                before(:all) do
       -          User.create!(:login => 'test 1', :created_at => Time.now - 1.send(grouping), :profile_visits => 1)
       -          User.create!(:login => 'test 2', :created_at => Time.now - 3.send(grouping), :profile_visits => 2)
       -          User.create!(:login => 'test 3', :created_at => Time.now - 3.send(grouping), :profile_visits => 3)
       +          
                end
        
       -        describe do
       -
       -          before do
       -            @grouping = Kvlr::ReportsAsSparkline::Grouping.new(grouping)
       -            @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :grouping => grouping, :limit => 10)
       -            @result = @report.run
       -          end
       -
       -          it "should return an array starting reporting period (Time.now - (limit - 1).#{grouping.to_s})" do
       -            @result.first[0].should == Kvlr::ReportsAsSparkline::ReportingPeriod.new(@grouping, Time.now - 9.send(grouping)).date_time
       -          end
       +        
        
       -          it "should return data ending with with the current reporting period" do
       -            @result.last[0].should == Kvlr::ReportsAsSparkline::ReportingPeriod.new(@grouping).date_time
       -          end
       +        
        
       +        after(:all) do
       +          User.destroy_all
                end
        
       -        it 'should return correct data for aggregation :count' do
       -          @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :count, :grouping => grouping, :limit => 10)
       -          result = @report.run.to_a
       -
       -          result[9][1].should == 0.0
       -          result[8][1].should == 1.0
       -          result[7][1].should == 0.0
       -          result[6][1].should == 2.0
       +        after(:each) do
       +          Kvlr::ReportsAsSparkline::ReportCache.destroy_all
                end
        
       -        it 'should return correct data for aggregation :sum' do
       -          @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :sum, :grouping => grouping, :value_column => :profile_visits, :limit => 10)
       -          result = @report.run().to_a
       +      end
        
       -          result[9][1].should == 0.0
       -          result[8][1].should == 1.0
       -          result[7][1].should == 0.0
       -          result[6][1].should == 5.0
       -        end
       +    end
        
       -        it 'should return correct data for aggregation :count when custom conditions are specified' do
       -          @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :count, :grouping => grouping, :limit => 10)
       -          result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']]).to_a
       +    for grouping in [:hour, :day, :week, :month] do
        
       -          result[9][1].should == 0.0
       -          result[8][1].should == 1.0
       -          result[7][1].should == 0.0
       -          result[6][1].should == 1.0
       -        end
       +      describe "for grouping #{grouping.to_s}" do
        
       -        it 'should return correct data for aggregation :sum when custom conditions are specified' do
       -          @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations, :aggregation => :sum, :grouping => grouping, :value_column => :profile_visits, :limit => 10)
       -          result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2']]).to_a
       +        [true, false].each do |live_data|
       +
       +          describe "with :live_data = #{live_data}" do
       +
       +            before(:all) do
       +              User.create!(:login => 'test 1', :created_at => Time.now,                    :profile_visits => 2)
       +              User.create!(:login => 'test 2', :created_at => Time.now - 1.send(grouping), :profile_visits => 1)
       +              User.create!(:login => 'test 3', :created_at => Time.now - 3.send(grouping), :profile_visits => 2)
       +              User.create!(:login => 'test 4', :created_at => Time.now - 3.send(grouping), :profile_visits => 3)
       +            end
       +
       +            describe do
       +
       +              before do
       +                @grouping = Kvlr::ReportsAsSparkline::Grouping.new(grouping)
       +                @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations,
       +                  :grouping => grouping,
       +                  :limit => 10,
       +                  :live_data => live_data
       +                )
       +                @result = @report.run
       +              end
       +
       +              it "should return an array starting reporting period (Time.now - limit.#{grouping.to_s})" do
       +                @result.first[0].should == Kvlr::ReportsAsSparkline::ReportingPeriod.new(@grouping, Time.now - 10.send(grouping)).date_time
       +              end
       +
       +              if live_data
       +                it "should return data ending with the current reporting period" do
       +                  @result.last[0].should == Kvlr::ReportsAsSparkline::ReportingPeriod.new(@grouping).date_time
       +                end
       +              else
       +                it "should return data ending with the reporting period before the current" do
       +                  @result.last[0].should == Kvlr::ReportsAsSparkline::ReportingPeriod.new(@grouping).previous.date_time
       +                end
       +              end
       +
       +            end
       +
       +            it 'should return correct data for aggregation :count' do
       +              @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations,
       +                :aggregation => :count,
       +                :grouping    => grouping,
       +                :limit       => 10,
       +                :live_data   => live_data
       +              )
       +              result = @report.run.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
       +
       +            it 'should return correct data for aggregation :sum' do
       +              @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations,
       +                :aggregation  => :sum,
       +                :grouping     => grouping,
       +                :value_column => :profile_visits,
       +                :limit        => 10,
       +                :live_data    => live_data
       +              )
       +              result = @report.run().to_a
       +
       +              result[10][1].should == 2.0 if live_data
       +              result[9][1].should  == 1.0
       +              result[8][1].should  == 0.0
       +              result[7][1].should  == 5.0
       +              result[6][1].should  == 0.0
       +            end
       +
       +            it 'should return correct data for aggregation :count when custom conditions are specified' do
       +              @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations,
       +                :aggregation => :count,
       +                :grouping    => grouping,
       +                :limit       => 10,
       +                :live_data   => live_data
       +              )
       +              result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2', 'test 4']]).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  == 1.0
       +              result[6][1].should  == 0.0
       +            end
       +
       +            it 'should return correct data for aggregation :sum when custom conditions are specified' do
       +              @report = Kvlr::ReportsAsSparkline::Report.new(User, :registrations,
       +                :aggregation  => :sum,
       +                :grouping     => grouping,
       +                :value_column => :profile_visits,
       +                :limit        => 10,
       +                :live_data    => live_data
       +              )
       +              result = @report.run(:conditions => ['login IN (?)', ['test 1', 'test 2', 'test 4']]).to_a
       +
       +              result[10][1].should == 2.0 if live_data
       +              result[9][1].should  == 1.0
       +              result[8][1].should  == 0.0
       +              result[7][1].should  == 3.0
       +              result[6][1].should  == 0.0
       +            end
        
       -          result[9][1].should == 0.0
       -          result[8][1].should == 1.0
       -          result[7][1].should == 0.0
       -          result[6][1].should == 2.0
       -        end
       +          end
        
       -        after(:all) do
       -          User.destroy_all
       -        end
       +          after(:all) do
       +            User.destroy_all
       +          end
        
       -        after(:each) do
       -          Kvlr::ReportsAsSparkline::ReportCache.destroy_all
                end
        
              end
        
            end
        
       +    after(:each) do
       +      Kvlr::ReportsAsSparkline::ReportCache.destroy_all
       +    end
       +
          end
        
          describe '#read_data' do
       @@ -228,7 +309,8 @@ describe Kvlr::ReportsAsSparkline::Report do
                    :grouping     => :day,
                    :date_column  => :created_at,
                    :value_column => :id,
       -            :conditions   => []
       +            :conditions   => [],
       +            :live_data    => true
                  })
                }.should_not raise_error(ArgumentError)
              end
 (DIR) diff --git a/spec/classes/reporting_period_spec.rb b/spec/classes/reporting_period_spec.rb
       @@ -204,32 +204,32 @@ describe Kvlr::ReportsAsSparkline::ReportingPeriod do
              DateTime.stub!(:now).and_return(@now)
            end
        
       -    it 'should return a reporting period with the date part of (DateTime.now - (limit - 1).hours) with minutes = seconds = 0 for grouping :hour' do
       +    it 'should return a reporting period with the date part of (DateTime.now - limit.hours with minutes = seconds = 0 for grouping :hour' do
              reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.first(Kvlr::ReportsAsSparkline::Grouping.new(:hour), 3)
       -      expected = @now - 2.hours
       +      expected = @now - 3.hours
        
              reporting_period.date_time.should == DateTime.new(expected.year, expected.month, expected.day, expected.hour, 0, 0)
            end
        
       -    it 'should return a reporting period with the date part of (DateTime.now - (limit - 1).days) for grouping :day' do
       +    it 'should return a reporting period with the date part of (DateTime.now - limit.days) for grouping :day' do
              reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.first(Kvlr::ReportsAsSparkline::Grouping.new(:day), 3)
       -      expected = @now - 2.days
       +      expected = @now - 3.days
        
              reporting_period.date_time.should == Date.new(expected.year, expected.month, expected.day)
            end
        
       -    it 'should return a reporting period with the date of the first day of the month at (DateTime.now - (limit - 1).weeks) for grouping :month' do
       +    it 'should return a reporting period with the date of the first day of the month at (DateTime.now - limit.months) for grouping :month' do
              DateTime.stub!(:now).and_return(DateTime.new(2008, 12, 31, 0, 0, 0))
              reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.first(Kvlr::ReportsAsSparkline::Grouping.new(:month), 3)
        
       -      reporting_period.date_time.should == DateTime.new(2008, 10, 1)
       +      reporting_period.date_time.should == DateTime.new(2008, 9, 1)
            end
        
       -    it 'should return a reporting period with the date of the monday of the week at (DateTime.now - (limit - 1).weeks) for grouping :week' do
       +    it 'should return a reporting period with the date of the monday of the week at (DateTime.now - limit.weeks) for grouping :week' do
              DateTime.stub!(:now).and_return(DateTime.new(2008, 12, 31, 0, 0, 0)) #wednesday
              reporting_period = Kvlr::ReportsAsSparkline::ReportingPeriod.first(Kvlr::ReportsAsSparkline::Grouping.new(:week), 3)
        
       -      reporting_period.date_time.should == DateTime.new(2008, 12, 15) #the monday 2 weeks earlier
       +      reporting_period.date_time.should == DateTime.new(2008, 12, 8) #the monday 3 weeks earlier
            end
        
          end
 (DIR) diff --git a/spec/other/report_method_spec.rb b/spec/other/report_method_spec.rb
       @@ -13,16 +13,15 @@ describe Kvlr::ReportsAsSparkline do
            it 'should include all data when invoked on the base model class' do
              result = User.registrations_report.to_a
        
       -      result.length.should == 10
       -      result[8][1].should  == 1.0
       -      result[7][1].should  == 2.0
       +      result[9][1].should == 1.0
       +      result[8][1].should == 2.0
            end
        
            it 'should include only data for instances of the inherited model when invoked on the inherited model class' do
              result = SpecialUser.registrations_report.to_a
        
       -      result.length.should == 10
       -      result[7][1].should  == 1.0
       +      result[9][1].should == 0.0
       +      result[8][1].should == 1.0
            end
        
            after(:all) do