module ActiveReporting

Constants

AGGREGATES
BadMetricLookupClass
InvalidDimensionLabel
RansackNotAvailable
UnknownAggregate
UnknownDimension
UnknownDimensionFilter
UnknownJoinMethod
UnknownMetric
VERSION

Public Class Methods

fetch_metric(name) click to toggle source
# File lib/active_reporting.rb, line 24
def self.fetch_metric(name)
  klass = Configuration.metric_lookup_class
  unless defined?(klass.constantize)
    raise BadMetricLookupClass,
          "#{klass} not defined. Please define a class responsible for looking up a metric by name." \
          ' You may define your own class and set it with `ActiveReporting::Configuration.metric_lookup_class=`.'
  end
  unless klass.constantize.respond_to?(:lookup)
    raise BadMetricLookupClass, "#{klass} needs to define a class method called 'lookup'"
  end
  klass.constantize.lookup(name)
end

Public Instance Methods

apply_dimension_callbacks() click to toggle source
# File lib/active_reporting/report.rb, line 143
def apply_dimension_callbacks
  @dimensions.each do |dimension|
    callback = dimension.label_callback
    next unless callback
    key = "#{dimension.name}_#{dimension.label}"
    @data.each do |hash|
      hash[key] = callback.call(hash[key])
    end
  end
end
datetime_drill_label_fragment(column) click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 182
def datetime_drill_label_fragment(column)
  if model.connection.adapter_name == "Mysql2"
    datetime_drill_mysql(column)
  else # Postgress
    datetime_drill_postgress(column)
  end
end
datetime_drill_mysql(column) click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 199
def datetime_drill_mysql(column)
  case @datetime_drill.to_sym
  when :microseconds
    "MICROSECOND(#{column})"
  when :milliseconds
    "MICROSECOND(#{column}) DIV 1000"
  when :second
    "SECOND(#{column})"
  when :minute
    "MINUTE(#{column})"
  when :hour
    "HOUR(#{column})"
  when :day
    "DAY(#{column})"
  when :week
    "WEEKDAY(#{column})"
  when :month
    "MONTH(#{column})"
  when :quarter
    "QUARTER(#{column})"
  when :year
    "YEAR(#{column})"
  when :decade
    "YEAR(#{column}) DIV 10"
  when :century
    "YEAR(#{column}) DIV 100"
  when :millennium
    "YEAR(#{column}) DIV 1000"
  when :date
    "DATE(#{column})"
  end
end
datetime_drill_postgress(column) click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 190
def datetime_drill_postgress(column)
  case @datetime_drill.to_sym
  when :date
    "DATE('#{column}')"
  else
    "DATE_TRUNC('#{@datetime_drill}', #{column})"
  end
end
determin_aggregate(agg) click to toggle source
# File lib/active_reporting/metric.rb, line 46
def determin_aggregate(agg)
  raise UnknownAggregate, "Unknown aggregate '#{agg}'" unless AGGREGATES.include?(agg)
  @aggregate = agg
end
determine_datetime_drill(datetime_drill) click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 131
def determine_datetime_drill(datetime_drill)
  return unless datetime_drill
  validate_supported_database_for_datetime_hierarchies
  validate_against_datetime_hierarchies(datetime_drill)
  validate_label_is_datetime
  @datetime_drill = datetime_drill
end
determine_join_method(join_method) click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 139
def determine_join_method(join_method)
  if join_method.blank?
    @join_method = ReportingDimension::JOIN_METHODS[:joins]
  elsif ReportingDimension::JOIN_METHODS.include?(join_method)
    @join_method = join_method
  else
    raise UnknownJoinMethod, "Method '#{join_method}' not included in '#{ReportingDimension::JOIN_METHODS.values}'"
  end
end
determine_label_name(label_name) click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 119
def determine_label_name(label_name)

  if label_name
    @label_name = label_name
  else
    @label_name = name
    @label_name += "_#{@label}" if (type == Dimension::TYPES[:standard] && @label != :name)
    @label_name += "_#{@datetime_drill}" if @datetime_drill
  end
  @label_name
end
dimension_fact_model() click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 250
def dimension_fact_model
  @dimension_fact_model ||= klass.fact_model
end
dimension_joins(join_method) click to toggle source
# File lib/active_reporting/report.rb, line 88
def dimension_joins(join_method)
  @dimensions.select { |d| d.type == Dimension::TYPES[:standard] && d.join_method == join_method }.
              map { |d| d.name.to_sym }
end
group_by_statement() click to toggle source
# File lib/active_reporting/report.rb, line 93
def group_by_statement
  @dimensions.map { |d| d.group_by_statement(with_identifier: @dimension_identifiers) }
end
having_statement() click to toggle source
# File lib/active_reporting/report.rb, line 128
def having_statement
  @metric_filter.map do |operator, value|
    "#{select_aggregate} #{AGGREGATE_FUNCTION_OPERATORS[operator]} #{value.to_f}"
  end.join(' AND ')
end
identifier_fragment() click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 232
def identifier_fragment
  "#{klass.quoted_table_name}.#{model.connection.quote_column_name(klass.primary_key)}"
end
identifier_fragment_alias() click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 236
def identifier_fragment_alias
  "#{model.connection.quote_column_name("#{name}_identifier")}"
end
label_fragment() click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 240
def label_fragment
  fragment = "#{klass.quoted_table_name}.#{model.connection.quote_column_name(@label)}"
  fragment = datetime_drill_label_fragment(fragment) if @datetime_drill
  fragment
end
label_fragment_alias() click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 246
def label_fragment_alias
  "#{model.connection.quote_column_name(@label_name)}"
end
order_by_statement() click to toggle source
# File lib/active_reporting/report.rb, line 134
def order_by_statement
  [].tap do |o|
    @ordering.each do |dimension_key, direction|
      dim = @dimensions.detect { |d| d.name.to_sym == dimension_key.to_sym }
      o << dim.order_by_statement(direction: direction) if dim
    end
  end
end
partition_dimension_filters(user_dimension_filter) click to toggle source
# File lib/active_reporting/report.rb, line 44
def partition_dimension_filters(user_dimension_filter)
  @dimension_filters = { ransack: {}, scope: {}, lambda: {} }
  user_dimension_filter.merge(@metric.dimension_filter).each do |key, value|
    dm = fact_model.find_dimension_filter(key.to_sym)
    @dimension_filters[dm.type][dm] = value
  end
end
process_lambda_dimension_filter(chain) click to toggle source
# File lib/active_reporting/report.rb, line 108
def process_lambda_dimension_filter(chain)
  @dimension_filters[:lambda].each do |df, args|
    chain = if [true, 'true'].include?(args)
              chain.scoping { model.instance_exec(&df.body) }
            else
              chain.scoping { model.instance_exec(args, &df.body) }
            end
  end
  chain
end
process_ransack_dimension_filter(chain) click to toggle source
# File lib/active_reporting/report.rb, line 119
def process_ransack_dimension_filter(chain)
  ransack_hash = {}
  @dimension_filters[:ransack].each do |dm, value|
    ransack_hash[dm.name] = value
  end
  chain = chain.ransack(ransack_hash).result if ransack_hash.present?
  chain
end
process_scope_dimension_filter(chain) click to toggle source
# File lib/active_reporting/report.rb, line 97
def process_scope_dimension_filter(chain)
  @dimension_filters[:scope].each do |dm, args|
    chain = if [true, 'true'].include?(args)
              chain.public_send(dm.name)
            else
              chain.public_send(dm.name, args)
            end
  end
  chain
end
select_aggregate() click to toggle source
# File lib/active_reporting/report.rb, line 79
def select_aggregate
  case @metric.aggregate
  when :count
    'COUNT(*)'
  else
    "#{@metric.aggregate.to_s.upcase}(#{fact_model.measure})"
  end
end
select_statement() click to toggle source
# File lib/active_reporting/report.rb, line 73
def select_statement
  ss = ["#{select_aggregate} AS #{@metric.name}"]
  ss += @dimensions.map { |d| d.select_statement(with_identifier: @dimension_identifiers) }
  ss.flatten
end
statement() click to toggle source
# File lib/active_reporting/report.rb, line 52
def statement
  parts = {
    select: select_statement,
    joins: dimension_joins(ReportingDimension::JOIN_METHODS[:joins]),
    left_outer_joins: dimension_joins(ReportingDimension::JOIN_METHODS[:left_outer_joins]),
    group: group_by_statement,
    having: having_statement,
    order: order_by_statement
  }

  statement = ([model] + parts.keys).inject do |chain, method|
    chain.public_send(method, parts[method])
  end

  statement = process_scope_dimension_filter(statement)
  statement = process_lambda_dimension_filter(statement)
  statement = process_ransack_dimension_filter(statement)

  statement
end
validate_against_datetime_hierarchies(hierarchical_label) click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 167
def validate_against_datetime_hierarchies(hierarchical_label)
  return if DATETIME_HIERARCHIES.include?(hierarchical_label.to_sym)
  raise InvalidDimensionLabel, "#{hierarchical_label} is not a valid datetime grouping label in #{name}"
end
validate_against_fact_model_properties(hierarchical_label) click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 177
def validate_against_fact_model_properties(hierarchical_label)
  return if dimension_fact_model.hierarchical_levels.include?(hierarchical_label.to_sym)
  raise InvalidDimensionLabel, "#{hierarchical_label} is not a hierarchical label in #{name}"
end
validate_dimension_is_hierachical(hierarchical_label) click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 155
def validate_dimension_is_hierachical(hierarchical_label)
  return if hierarchical?
  raise InvalidDimensionLabel, "#{name} must be hierarchical to use label #{hierarchical_label}"
end
validate_hierarchical_label(hierarchical_label) click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 149
def validate_hierarchical_label(hierarchical_label)
  validate_dimension_is_hierachical(hierarchical_label)
  validate_against_fact_model_properties(hierarchical_label)
  true
end
validate_label_is_datetime() click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 172
def validate_label_is_datetime
  return if dimension_fact_model.model.column_for_attribute(@label).type == :datetime
  raise InvalidDimensionLabel, "'#{@label}' is not a datetime column"
end
validate_supported_database_for_datetime_hierarchies() click to toggle source
# File lib/active_reporting/reporting_dimension.rb, line 160
def validate_supported_database_for_datetime_hierarchies
  return if SUPPORTED_DBS.include?(model.connection.adapter_name)
  raise InvalidDimensionLabel,
        "Cannot utilize datetime grouping for #{name}; " \
        "database #{model.connection.adapter_name} is not supported"
end