Build Status

simple_drilldown offers a simple way to define axis to filter and group records for analysis. The result is a record count for the selected filter and distribution and the option to list and export the actual records.



For a given schema:

ActiveRecord::Schema.define(version: 20141204155251) do
  create_table "users" do |t|
    t.string "name",   limit: 16, null: false

  create_table "posts" do |t|
    t.string   "title",      null: false
    t.text     "body",       null: false
    t.integer  "user_id",    null: false
    t.datetime "published_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false

  create_table "comments" do |t|
    t.integer  "post_id", null: false
    t.integer  "user_id",    null: false
    t.string   "title",   null: false
    t.text     "body",    null: false
    t.integer  "rating",  null: false
    t.datetime "created_at"
    t.datetime "updated_at"


We have three entities:

class Post < ActiveRecord::Base
  belongs_to :user
  has_many :comments

class User < ActiveRecord::Base
  has_many :comments
  has_many :posts

class Comment < ActiveRecord::Base
  belongs_to :post
  belongs_to :user


Create a new controller to focus on posts. Each drilldown controller focuses on one main entity.

bin/rails g drilldown_controller User
class PostsDrilldownController < DrilldownController

  # What fields should be displayed as default when listing actual Post records.
  default_fields %w{created_at user title}

  # The main focus of the drilldown
  target_class Post

  # How should we count the reords?
  select "count(*) as count".freeze

  # When listing records, what relations should be included for optimization?
  list_includes :user, :comments

  # In what order should records be listed?
  list_order 'posts.created_at'

  # Field definitions when listing records
  field :created_at
  field :title

  # The "attr_method" option transforms the value from the database to a
  # readable form.
  field :user, attr_method: lambda { |post| }
  field :body, attr_method: lambda { |post| post.body[0..32] }
  field :comments, attr_method: lambda { |post| post.comments.count }

  dimension :calendar_date, "DATE(posts.created_at)", interval: true
  dimension :comments, "SELECT count(*) FROM comments c WHERE c.post_id ="
  dimension :user, '', includes: :user
  dimension :day_of_month, "date_part('day', posts.created_at)"
  dimension :day_of_week, "CASE WHEN date_part('dow', posts.created_at) = 0 THEN 7 ELSE date_part('dow', posts.created_at) END",
            label_method: lambda { |day_no| Date::DAYNAMES[day_no.to_i % 7] }
  dimension :hour_of_day, "date_part('hour', posts.created_at"
  dimension :month, "date_part('month', posts.created_at",
            label_method: lambda { |month_no| Date::MONTHNAMES[month_no.to_i] }
  dimension :week, "date_part('week', posts.created_at)"
  dimension :year, "date_part('year', posts.created_at)"

The controller inherits the index action and other actions to display the results.


You need the following views:

Excel export

TODO: Write about Excel export.

{excel_type: 'Number', excel_style: 'ThreeDecimalNumberFormat'}


Add this line to your application's Gemfile:

gem 'simple_drilldown'

And then execute:

$ bundle

Or install it yourself as:

$ gem install simple_drilldown


  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request


The gem is available as open source under the terms of the MIT License.