wip - reportable - Fork of reportable required by WarVox, from hdm/reportable.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 8cb8704ce68c2699bb73c38d675b6277943fa909
 (DIR) parent 7ab93765296ffddba9b6c4ced20188a5136fc6c3
 (HTM) Author: Cristi Balan <evil@che.lu>
       Date:   Mon, 13 Jan 2014 12:58:24 +0200
       
       wip
       Diffstat:
         M Gemfile                             |      14 +++++---------
         M lib/saulabs/reportable/report.rb    |      17 ++++++++---------
         M lib/saulabs/reportable/report_cach… |      53 ++++++++++++++-----------------
         M spec/classes/report_cache_spec.rb   |      21 ++++-----------------
         M spec/spec_helper.rb                 |       9 +++++++--
       
       5 files changed, 47 insertions(+), 67 deletions(-)
       ---
 (DIR) diff --git a/Gemfile b/Gemfile
       @@ -1,16 +1,12 @@
        source "http://rubygems.org"
        
       -gem 'rails',         '~> 3.2.0'
       -gem 'activerecord',  '~> 3.2.0', :require => 'active_record'
       -gem 'activesupport', '~> 3.2.0', :require => 'active_support'
       -gem 'actionpack',    '~> 3.2.0', :require => 'action_pack'
       +gem 'rails', '= 4.1.0.beta1'
       +gem 'protected_attributes', github: "rails/protected_attributes"
        
       -gem 'sqlite3-ruby', '>= 1.2.0'
       -gem 'mysql',                                 '>= 2.8.0'
       -gem 'pg',                                         '>= 0.9.0'
       -gem 'tzinfo',                         '>= 0.3.0'
       +gem 'sqlite3'
       +# gem 'mysql',  '>= 2.8.0'
       +gem 'pg', '<= 0.15.0' # https://groups.google.com/forum/#!topic/ruby-pg/5_ylGmog1S4
        
       -gem 'rake',       '>= 0.8.7'
        gem 'rspec',      '~> 2.8.0'
        gem 'simplecov'
        gem 'excellent',  '>= 1.5.4'
 (DIR) diff --git a/lib/saulabs/reportable/report.rb b/lib/saulabs/reportable/report.rb
       @@ -119,15 +119,14 @@ module Saulabs
        
                def read_data(begin_at, end_at, options)
                  conditions = setup_conditions(begin_at, end_at, options[:conditions])
       -          @klass.send(@aggregation,
       -            @value_column,
       -            :conditions => conditions,
       -            :include    => options[:include],
       -            :distinct   => options[:distinct],
       -            :group      => options[:grouping].to_sql("#{ActiveRecord::Base.connection.quote_table_name(@klass.table_name)}.#{ActiveRecord::Base.connection.quote_column_name(@date_column.to_s)}"),
       -            :order      => "#{options[:grouping].to_sql("#{ActiveRecord::Base.connection.quote_table_name(@klass.table_name)}.#{ActiveRecord::Base.connection.quote_column_name(@date_column.to_s)}")} ASC",
       -            :limit      => options[:limit]
       -          )
       +          table_name = ActiveRecord::Base.connection.quote_table_name(@klass.table_name)
       +          date_column = ActiveRecord::Base.connection.quote_column_name(@date_column.to_s)
       +          grouping = options[:grouping].to_sql("#{table_name}.#{date_column}")
       +          order    = "#{grouping} ASC"
       +
       +          @klass.where(conditions).includes(options[:include]).distinct(options[:distinct]).
       +            group(grouping).order(order).limit(options[:limit]).
       +            calculate(@aggregation, @value_column)
                end
        
                def setup_conditions(begin_at, end_at, custom_conditions = [])
 (DIR) diff --git a/lib/saulabs/reportable/report_cache.rb b/lib/saulabs/reportable/report_cache.rb
       @@ -20,7 +20,7 @@ module Saulabs
              validates_presence_of :value
              validates_presence_of :reporting_period
        
       -      attr_accessible :model_name, :report_name, :grouping, :aggregation, :value, :reporting_period, :conditions
       +      # attr_accessible :model_name, :report_name, :grouping, :aggregation, :value, :reporting_period, :conditions
        
              self.skip_time_zone_conversion_for_attributes = [:reporting_period]
        
       @@ -40,10 +40,7 @@ module Saulabs
              #   Saulabs::Reportable::ReportCache.clear_for(User, :registrations)
              #
              def self.clear_for(klass, report)
       -        self.delete_all(:conditions => {
       -          :model_name  => klass.name,
       -          :report_name => report.to_s
       -        })
       +        self.where(model_name: klass.name, report_name: report.to_s).delete_all
              end
        
              # Processes the report using the respective cache.
       @@ -88,8 +85,8 @@ module Saulabs
              private
        
                def self.prepare_result(new_data, cached_data, report, options)
       -          new_data = new_data.map { |data| [ReportingPeriod.from_db_string(options[:grouping], data[0]), data[1]] }
       -          cached_data.map! { |cached| [ReportingPeriod.new(options[:grouping], cached.reporting_period), cached.value] }
       +          new_data = new_data.to_a.map { |data| [ReportingPeriod.from_db_string(options[:grouping], data[0]), data[1]] }
       +          cached_data.to_a.map! { |cached| [ReportingPeriod.new(options[:grouping], cached.reporting_period), cached.value] }
                  current_reporting_period = ReportingPeriod.new(options[:grouping])
                  reporting_period = get_first_reporting_period(options)
                  result = []
       @@ -137,35 +134,31 @@ module Saulabs
                end
        
                def self.read_cached_data(report, options)
       -          options[:conditions] ||= []
       -          conditions = [
       -            %w(model_name report_name grouping aggregation conditions).map do |column_name|
       -              "#{self.connection.quote_column_name(column_name)} = ?"
       -            end.join(' AND '),
       -            report.klass.to_s,
       -            report.name.to_s,
       -            options[:grouping].identifier.to_s,
       -            report.aggregation.to_s,
       -            serialize_conditions(options[:conditions])
       -          ]
       -          first_reporting_period = get_first_reporting_period(options)
       +          conditions = build_conditions_for_reading_cached_data(report, options)
       +          self.where(conditions).limit(options[:limit]).order('reporting_period ASC')
       +        end
       +
       +        def self.build_conditions_for_reading_cached_data(report, options)
       +          start_date = get_first_reporting_period(options).date_time
       +
       +          conditions = where('reporting_period >= ?', start_date).where(
       +            model_name: report.klass.to_s,
       +            report_name: report.name.to_s,
       +            grouping: options[:grouping].identifier.to_s,
       +            aggregation: report.aggregation.to_s,
       +            conditions: serialize_conditions(options[:conditions] || [])
       +          )
       +
                  if options[:end_date]
       -            conditions.first << ' AND reporting_period BETWEEN ? AND ?'
       -            conditions << first_reporting_period.date_time
       -            conditions << ReportingPeriod.new(options[:grouping], options[:end_date]).date_time
       +            end_date = ReportingPeriod.new(options[:grouping], options[:end_date]).date_time
       +            conditions.where('reporting_period <= ?', end_date)
                  else
       -            conditions.first << ' AND reporting_period >= ?'
       -            conditions << first_reporting_period.date_time
       +            conditions
                  end
       -          self.all(
       -            :conditions => conditions,
       -            :limit      => options[:limit],
       -            :order      => 'reporting_period ASC'
       -          )
                end
        
                def self.read_new_data(cached_data, options, &block)
       -          return [] if !options[:live_data] && cached_data.length == options[:limit]
       +          return [] if !options[:live_data] && cached_data.size == options[:limit]
        
                  first_reporting_period_to_read = get_first_reporting_period_to_read(cached_data, options)
                  last_reporting_period_to_read = options[:end_date] ? ReportingPeriod.new(options[:grouping], options[:end_date]).last_date_time : nil
 (DIR) diff --git a/spec/classes/report_cache_spec.rb b/spec/classes/report_cache_spec.rb
       @@ -91,19 +91,6 @@ describe Saulabs::Reportable::ReportCache do
        
          end
        
       -  describe '.clear_for' do
       -
       -    it 'should delete all entries in the cache for the klass and report name' do
       -      Saulabs::Reportable::ReportCache.should_receive(:delete_all).once.with(:conditions => {
       -        :model_name  => User.name,
       -        :report_name => 'registrations'
       -      })
       -
       -      Saulabs::Reportable::ReportCache.clear_for(User, :registrations)
       -    end
       -
       -  end
       -
          describe '.process' do
        
            before do
       @@ -136,7 +123,7 @@ describe Saulabs::Reportable::ReportCache do
              end
        
              it 'should yield the first reporting period if not all required data could be retrieved from the cache' do
       -        Saulabs::Reportable::ReportCache.stub!(:all).and_return([Saulabs::Reportable::ReportCache.new])
       +        Saulabs::Reportable::ReportCache.stub!(:read_cached_data).and_return([Saulabs::Reportable::ReportCache.new])
        
                Saulabs::Reportable::ReportCache.process(@report, @options) do |begin_at, end_at|
                  begin_at.should == Saulabs::Reportable::ReportingPeriod.first(@report.options[:grouping], @report.options[:limit]).date_time
       @@ -152,7 +139,7 @@ describe Saulabs::Reportable::ReportCache do
                )
                cached = Saulabs::Reportable::ReportCache.new
                cached.stub!(:reporting_period).and_return(reporting_period.date_time)
       -        Saulabs::Reportable::ReportCache.stub!(:all).and_return(Array.new(@report.options[:limit] - 1, Saulabs::Reportable::ReportCache.new), cached)
       +        Saulabs::Reportable::ReportCache.stub!(:read_cached_data).and_return(Array.new(@report.options[:limit] - 1, Saulabs::Reportable::ReportCache.new), cached)
        
                Saulabs::Reportable::ReportCache.process(@report, @options) do |begin_at, end_at|
                  begin_at.should == reporting_period.date_time
       @@ -166,7 +153,7 @@ describe Saulabs::Reportable::ReportCache do
            describe 'with :live_data = false' do
        
              it 'should not yield if all required data could be retrieved from the cache' do
       -        Saulabs::Reportable::ReportCache.stub!(:all).and_return(Array.new(@report.options[:limit], Saulabs::Reportable::ReportCache.new))
       +        Saulabs::Reportable::ReportCache.stub!(:read_cached_data).and_return(Array.new(@report.options[:limit], Saulabs::Reportable::ReportCache.new))
        
                lambda {
                  Saulabs::Reportable::ReportCache.process(@report, @report.options) { raise YieldMatchException.new }
       @@ -174,7 +161,7 @@ describe Saulabs::Reportable::ReportCache do
              end
        
              it 'should yield to the block if no data could be retrieved from the cache' do
       -        Saulabs::Reportable::ReportCache.stub!(:all).and_return([])
       +        Saulabs::Reportable::ReportCache.stub!(:read_cached_data).and_return([])
        
                lambda {
                  Saulabs::Reportable::ReportCache.process(@report, @report.options) { raise YieldMatchException.new }
 (DIR) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
       @@ -27,8 +27,13 @@ require File.join(ROOT, 'lib', 'saulabs', 'reportable.rb')
        #   config.time_zone = 'Pacific Time (US & Canada)'
        # end
        
       -FileUtils.mkdir_p File.join(File.dirname(__FILE__), 'log')
       -ActiveRecord::Base.logger = ActiveSupport::BufferedLogger.new(File.dirname(__FILE__) + "/log/spec.log")
       +# FileUtils.mkdir_p File.join(File.dirname(__FILE__), 'log')
       +# ActiveRecord::Base.logger = ActiveSupport::BufferedLogger.new(File.dirname(__FILE__) + "/log/spec.log")
       +
       +RSpec.configure do |config|
       +  config.filter_run :focus => true
       +  config.run_all_when_everything_filtered = true
       +end
        
        databases = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'db', 'database.yml')))
        ActiveRecord::Base.establish_connection(databases[ENV['DB'] || 'sqlite3'])