Overview

When generating data for a report, the common approach is to specify measures and dimensions in the YAML file, but if you want to use any Ruby logic to generate the data, you can do so with a data_method.

To use a data_method, create a class method that takes properties as an argument and returns the data for the report:

# app/services/my_data_methods.rb

class MyDataMethods
  # { 'Bernice' => 191, 'Carlee' => 160, 'Edison' => 60, ... }
  def self.posts_by_author(properties)
    Post.joins(:author).group('authors.name').order('authors.name').count
  end
end

Then set data_method to that class method in the report's YAML file:

data_method: MyDataMethods.posts_by_author
chart:
  options:
    legend:
      display: false
    scales:
      xAxes:
      - scaleLabel:
          display: true
          labelString: Posts
      yAxes:
      - scaleLabel:
          display: true
          labelString: Author

The properties argument is a hash that contains data from the report's YAML file, form filter data, and context_params that were passed to render_report.

To see examples of the format of the data that should be returned by a data_method, see Data Methods > One Dimension and Data Methods > Two Dimensions.


To create the chart above, simply add the following YAML file and call render_report in any view:

YAML

config/reports_kit/reports/data_methods.yml

data_method: MyDataMethods.posts_by_author
chart:
  options:
    legend:
      display: false
    scales:
      xAxes:
      - scaleLabel:
          display: true
          labelString: Posts
      yAxes:
      - scaleLabel:
          display: true
          labelString: Author

Note: The "chart.options" option is passed to Chart.js, so any values supported by Chart.js are supported here, too.


View

app/views/my_controller/my_view.html.haml

= render_report 'data_methods'

Data Methods

app/services/my_data_methods.rb

class MyDataMethods
  # { 'Bernice' => 191, 'Carlee' => 160, 'Edison' => 60, ... }
  def self.posts_by_author(properties)
    Post.joins(:author).group('authors.name').order('authors.name').count
  end

  # [
  #   [["Jul 3, 2016", "Hilton"], 2],
  #   [["Jul 10, 2016", "Hilton"], 2],
  #   ...
  #   [["Jul 3, 2016", "Carlee"], 3],
  #   [["Jul 10, 2016", "Carlee"], 5],
  #   ...
  # ]
  def self.posts_by_created_at_week_and_author(properties)
    # The `group_by_week` method is provided by the `groupdate` gem.
    Post.joins(:author).group_by_week('posts.created_at').group('authors.name').count.map do |(date, author_name), count|
      [[date.strftime('%b %-d, %Y'), author_name], count]
    end
  end

  # { 'Bernice' => 191, 'Carlee' => 160, 'Edison' => 60, ... }
  def self.posts_by_author_with_filters(properties)
    ui_filters = properties[:ui_filters]

    posts = Post.joins(:author).group('authors.name').order('authors.name')
    posts = posts.where(created_at: ReportsKit.parse_date_range(ui_filters[:created_at])) if ui_filters[:created_at].present?
    posts = posts.where(is_featured: true) if ui_filters[:is_featured]
    posts = posts.where(author_id: ui_filters[:author]) if ui_filters[:author].present?
    posts = posts.where('title ILIKE ?', "%#{ui_filters[:title]}%") if ui_filters[:title].present?
    posts.count
  end
end

Model

app/models/post.rb

class Post < ApplicationRecord
  belongs_to :author
  has_many :post_views, dependent: :destroy
  has_many :posts_tags, dependent: :destroy
  has_many :tags, through: :posts_tags

  include ReportsKit::Model
  reports_kit do
    aggregation :average_time_to_publish, [:average, 'posts.published_at - posts.created_at']
    contextual_filter :for_author, ->(relation, context_params) { relation.where(author_id: context_params[:author_id]) }
    dimension :approximate_views_count, group: 'ROUND(posts.views_count, -1)'
    filter :is_published, :boolean, conditions: ->(relation) { relation.where(status: 'published') }
  end

  STATUSES = %w(draft private published).freeze

  def to_s
    title
  end
end

Model's Columns

id              integer
author_id       integer
title           string
status          string
published_at    datetime
is_featured     boolean
views_count     integer
created_at      datetime
updated_at      datetime