lib/saulabs/reportable/report.rb in reportable-1.2.0 vs lib/saulabs/reportable/report.rb in reportable-1.3.0

- old
+ new

@@ -52,10 +52,12 @@ # the period records are grouped in (+:hour+, +:day+, +:week+, +:month+); <b>Beware that <tt>reportable</tt> treats weeks as starting on monday!</b> # @option options [Fixnum] :limit (100) # the number of reporting periods to get (see +:grouping+) # @option options [Hash] :conditions ({}) # conditions like in +ActiveRecord::Base#find+; only records that match these conditions are reported; + # @option options [Hash] :include ({}) + # include like in +ActiveRecord::Base#find+; names associations that should be loaded alongside; the symbols named refer to already defined associations # @option options [Boolean] :live_data (false) # specifies whether data for the current reporting period is to be read; <b>if +:live_data+ is +true+, you will experience a performance hit since the request cannot be satisfied from the cache alone</b> # @option options [DateTime, Boolean] :end_date (false) # when specified, the report will only include data for the +:limit+ reporting periods until this date. # @@ -66,10 +68,12 @@ @date_column = (options[:date_column] || 'created_at').to_s @aggregation = options[:aggregation] || :count @value_column = (options[:value_column] || (@aggregation == :count ? 'id' : name)).to_s @options = { :limit => options[:limit] || 100, + :distinct => options[:distinct] || false, + :include => options[:include] || [], :conditions => options[:conditions] || [], :grouping => Grouping.new(options[:grouping] || :day), :live_data => options[:live_data] || false, :end_date => options[:end_date] || false } @@ -113,17 +117,18 @@ return options end def read_data(begin_at, end_at, options) conditions = setup_conditions(begin_at, end_at, options[:conditions]) - @klass.send(@aggregation, - @value_column, - :conditions => conditions, - :group => options[:grouping].to_sql(@date_column), - :order => "#{options[:grouping].to_sql(@date_column)} 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 = []) conditions = [@klass.send(:sanitize_sql_for_conditions, custom_conditions) || ''] conditions[0] += "#{(conditions[0].blank? ? '' : ' AND ')}#{ActiveRecord::Base.connection.quote_table_name(@klass.table_name)}.#{ActiveRecord::Base.connection.quote_column_name(@date_column.to_s)} " @@ -143,16 +148,16 @@ def ensure_valid_options(options, context = :initialize) case context when :initialize options.each_key do |k| - raise ArgumentError.new("Invalid option #{k}!") unless [:limit, :aggregation, :grouping, :date_column, :value_column, :conditions, :live_data, :end_date].include?(k) + raise ArgumentError.new("Invalid option #{k}!") unless [:limit, :aggregation, :grouping, :distinct, :include, :date_column, :value_column, :conditions, :live_data, :end_date].include?(k) end raise ArgumentError.new("Invalid aggregation #{options[:aggregation]}!") if options[:aggregation] && ![:count, :sum, :maximum, :minimum, :average].include?(options[:aggregation]) raise ArgumentError.new('The name of the column holding the value to sum has to be specified for aggregation :sum!') if [:sum, :maximum, :minimum, :average].include?(options[:aggregation]) && !options.key?(:value_column) when :run options.each_key do |k| - raise ArgumentError.new("Invalid option #{k}!") unless [:limit, :conditions, :grouping, :live_data, :end_date].include?(k) + raise ArgumentError.new("Invalid option #{k}!") unless [:limit, :conditions, :include, :grouping, :live_data, :end_date].include?(k) end end raise ArgumentError.new('Options :live_data and :end_date may not both be specified!') if options[:live_data] && options[:end_date] raise ArgumentError.new("Invalid grouping #{options[:grouping]}!") if options[:grouping] && ![:hour, :day, :week, :month].include?(options[:grouping]) raise ArgumentError.new("Invalid conditions: #{options[:conditions].inspect}!") if options[:conditions] && !options[:conditions].is_a?(Array) && !options[:conditions].is_a?(Hash)