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)