module ActiveReporter::Report::Definition

Constants

METRICS

Public Instance Methods

aggregator(name, aggregator_class, opts = {}) click to toggle source

Aggregators calculate the statistical data for the report into each dimension group. After grouping the data the aggregators calculate the values to be reported on. For example, if we use the dimensions Author name and Published date of blog posts in an online blog, we can then use aggregators on the Likes value to get the Sum of all Likes on all posts for each Published date for each Author name. There are multiple ways to aggregate this data, and so multiple aggregator types are provided.

Average aggregator would calculate the average value across all the data in the group.

Sum aggregator would calculate the sum total of all values across all the data in the group.

Additional aggregators are also available for many other calculation types

# File lib/active_reporter/report/definition.rb, line 48
def aggregator(name, aggregator_class, opts = {})
  aggregators[name.to_sym] = { axis_class: aggregator_class, opts: opts }
end
aggregators() click to toggle source
# File lib/active_reporter/report/definition.rb, line 52
def aggregators
  @aggregators ||= {}
end
autoreport_association_name_columns(reflection) click to toggle source

override this to change which columns of the association are used to auto-label it

# File lib/active_reporter/report/definition.rb, line 189
def autoreport_association_name_columns(reflection)
  %w(name email title)
end
autoreport_column(column) click to toggle source

can override this method to skip or change certain column declarations

# File lib/active_reporter/report/definition.rb, line 166
def autoreport_column(column)
  return if column.name == report_model.primary_key

  name, reflection = report_model.reflections.find { |_, reflection| reflection.foreign_key == column.name }
  case
  when reflection.present?
    column_name = (reflection.klass.column_names & autoreport_association_name_columns(reflection)).first
    if column_name.present?
      category_dimension name, expression: "#{reflection.klass.table_name}.#{column_name}", relation: ->(r) { r.joins(name) }
    else
      category_dimension column.name
    end
  when %i[datetime timestamp time date].include?(column.type)
    time_dimension column.name
  when %i[integer float decimal].include?(column.type)
    number_dimension column.name
  else
    category_dimension column.name
  end
end
autoreport_on(class_or_name) click to toggle source

autoreporting will automatically define dimensions based on columns

# File lib/active_reporter/report/definition.rb, line 159
def autoreport_on(class_or_name)
  report_on class_or_name
  report_model.columns.each(&method(:autoreport_column))
  count_aggregator(:count) if aggregators.blank?
end
available_aggregators() click to toggle source
# File lib/active_reporter/report/definition.rb, line 118
def available_aggregators
  aggregators.keys + calculators.keys + trackers.keys
end
available_dimensions() click to toggle source
# File lib/active_reporter/report/definition.rb, line 113
def available_dimensions
  dimensions.keys
end
calculator(name, calculator_class, opts = {}) click to toggle source

Calculators are special aggregators that perform calculations between report dimension data and a parent report. This could be used when generating a drill-down report with more specific data based on a specific row of a different report, where the parent report has larger dimension bins or fewer dimensions defined. For example, a parent report could group by Author only, and aggregate total Likes across all blog posts, the child report could group by Author and Published to provided more specific details. A calculator could then calculate the Ratio of Likes on a specific Published date vs the parent report's total Likes for that same specific Author. It can also be used to calculate values between the report data and the Totals report data, where the Totals report is the aggregation of all the data in the report combined. For example, if the report groups by Author we can aggregate total Likes across all blog posts for each Author. The Totals report would aggregate total Likes across all blog posts for all Author. A calculator can calculate the ratio of Total Likes vs the Author's total Likes.

A calculator only performs additional calculations on already aggregated data, so an :aggregator value matching the aggregator name must be passed in the opts. Additionally, you may optionally pass a :parent_aggregator if the name of this aggregator is different.

# File lib/active_reporter/report/definition.rb, line 72
def calculator(name, calculator_class, opts = {})
  calculators[name.to_sym] = { axis_class: calculator_class, opts: opts }
end
calculators() click to toggle source
# File lib/active_reporter/report/definition.rb, line 76
def calculators
  @calculators ||= {}
end
default_model() click to toggle source
# File lib/active_reporter/report/definition.rb, line 139
def default_model
  name.demodulize.sub(/Report$/, '').constantize
end
default_report_model() click to toggle source
# File lib/active_reporter/report/definition.rb, line 133
def default_report_model
  name.demodulize.sub(/Report$/, '').constantize
rescue NameError
  raise $!, "#{$!} cannot be used as `report_on` class, please configure `report_on` in the report class", $!.backtrace
end
dimension(name, dimension_class, opts = {}) click to toggle source

Dimensions define what we are reporting about. For example, some common dimensions would be the Name of the data being reported on and the Date it happened, such as the Author name and the Published date of blog posts in an online blog. These dimension configurations are the data points that a report can be grouped by, data in the group will all be aggregated together using the configured aggregators. Multiple dimension types are available for different grouping methods.

Category dimensions will do a normal GROUP BY on one specific field, this can also be used in conjunction with a filter to limit the GROUP BY values returned.

Bin dimensions group many rows into “bins” of a specified width, this is helpful when grouping by a datetime value by allowing you to set this bin width to :days or :months. In addition to the Time dimension you can use the Number dimensions with a bin, grouping numeric values into larger groups such as 10s or 100s.

# File lib/active_reporter/report/definition.rb, line 29
def dimension(name, dimension_class, opts = {})
  dimensions[name.to_sym] = { axis_class: dimension_class, opts: opts }
end
dimensions() click to toggle source
# File lib/active_reporter/report/definition.rb, line 33
def dimensions
  @dimensions ||= { totals: { axis_class: Dimension::Category, opts: { _expression: "'totals'" } } }
end
evaluator(name, evaluator_class, opts = {}) click to toggle source

block_evaluator(:chargeback_ratio) |row| supplemental_report_data.detect { |data| data[:id] == row[:id] / row }

# File lib/active_reporter/report/definition.rb, line 104
def evaluator(name, evaluator_class, opts = {})
  raise 'needs block' unless opts.include?(:block)
  evaluators[name.to_sym] = { axis_class: evaluator_class, opts: opts }
end
evaluators() click to toggle source
# File lib/active_reporter/report/definition.rb, line 109
def evaluators
  @evaluators ||= {}
end
inherited(subclass) click to toggle source

ensure subclasses gain any aggregators or dimensions defined on their parents

# File lib/active_reporter/report/definition.rb, line 154
def inherited(subclass)
  instance_values.each { |var, val| subclass.instance_variable_set(:"@#{var}", val.dup) }
end
report_model() click to toggle source
# File lib/active_reporter/report/definition.rb, line 143
def report_model
  @report_model ||= default_model
end
report_on(class_or_name) click to toggle source
# File lib/active_reporter/report/definition.rb, line 147
def report_on(class_or_name)
  @report_model = class_or_name.to_s.constantize
rescue NameError
  raise $!, "#{$!} cannot be used as `report_on` class", $!.backtrace
end
tracker(name, tracker_class, opts = {}) click to toggle source

Trackers are special aggregators that perform calculations between sequential bin dimension data. In order to use a tracker the last dimension configured in your report must be a bin dimension that defines a bin width so the tracker can determine the bin sequence. If a bin dimension with a bin width is not the last dimension configured tracker data will not be calculated. Any other dimensions are also considered when tracking data, if the value in any other dimension value changes between two rows the tracker data is not calculated. For example, if dimensions Author and Published are configured and an aggregator to sum Likes is configured, a tracker to calculate Likes delta may also be used. Each Published date the delta will be calculated, as long as the previous row has a Published date sequentially immediately adjacent to the current row. If the bin with is date, the dates 2020/06/05 and 2020/06/06 are adjacent, but if there are no blog posts for 2020/06/07 then the dela will not be calculated on the 2020/06/08 row since 2020/06/06 is not adjacent. Additionally, when the Author changes no delta will be calculated, even if the Published date on the row is sequentially immediately adjacent.

A tracker only performs additional calculations on already aggregated data, so an :aggregator value matching the aggregator name must be passed in the opts.

# File lib/active_reporter/report/definition.rb, line 95
def tracker(name, tracker_class, opts = {})
  trackers[name.to_sym] = { axis_class: tracker_class, opts: opts }
end
trackers() click to toggle source
# File lib/active_reporter/report/definition.rb, line 99
def trackers
  @trackers ||= {}
end