Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Benjamin Guez edited this page · 48 revisions

Defines column that will be used to display data.


  class UserGrid 
    include Datagrid

    scope do
      User.order("users.created_at desc").includes(:group)

    column(:group, :order => "") do
    column(:active, :header => "Activated") do |user|


Each column will be used to generate data. In order to create grid that display all users:

  grid =
  grid.header # => ["Group", "Name", "Disabled"]
  grid.rows   # => [
              #      ["Steve", "Spammers", true],
              #      [ "John", "Spoilers", true],
              #      ["Berry", "Good people", false]
              #    ]   # => Header & Rows

Column value

Column value can be defined by passing a block to Datagrid.column method.

Basic column value

If no block given column it is generated automatically by sending column name method to model.

  column(:name) # =>

The block could have no arguments(instance_eval for each asset will be used).

  column(:completed) { completed? }

If you don't like instance_eval you can use asset as first argument:

  column(:completed) { |asset| asset.completed? }

Advanced column value

For the most complicated columns you can also pass datagrid object itself:

  filter(:category) do |value|
    where("category LIKE '%#{value}%'")

  column(:exactly_matches_category) do |asset, grid|
    asset.category == grid.category

Another advanced use case (version >= 0.9.3):

class MerchantsGrid
 scope { Merchant }

  # Dummy filter is not automatically applied to scope
  filter(:period, :date, :range => true, :dummy => true)

  column(:number_of_purchases) do |merchant, grid|
    merchant.purchases.where(:created_at => grid.period).count

Sometimes you can even combine previously defined columns into new ones:

column(:total_sales) do |merchant|
column(:number_of_sales) do |merchant|
column(:average_order_value) do |_, _, row|
  row.total_sales / row.number_of_sales

Using database expression (version >= 1.1.0)

This allows to determine how a column should be selected. Right now it only supports ActiveRecord. If specified, it will add the string to the select. This is useful for data aggregation or to make transformations of the data directly in the database.

column(:count_of_users, 'count(user_id)')
column(:uppercase_name, 'upper(name)')

Note, that you should never specify the AS part, since it's added automatically.

HTML Columns (version >= 0.9.1)

Sometimes you might need a different formatting for column value in CSV and HTML. In this case you can use the following construction:

column(:name) do |asset|
  format( do |value|
    content_tag(:strong, value)

Now when you render an HTML table you will see <strong>NAME</strong> While in CSV (or any other non-HTML representation) it won't be wrapped with <strong> tag.

You can specify if given column should only appear in html view (via the :html option) :

column(:completed, :html => true) do |asset| 
  asset.completed? ? image_tag("green.gif") : image_tag("red.gif")
# or do it in partial
column(:actions, :html => true) do |asset|
  render :partial => "admin/assets/actions", :object => asset
# if you want to hide a column only from html view and have it only in csv export.
column(:id, :html => false)

Column Value cache (>= 1.3.0)

You can enable grid level cache for column values:

self.cached = true

In this way column values will be cached based on models primary keys You can define other cache key when model don't have primary key:

self.cached = proc {|model| model.identifier }

It is also helpful when aggregation queries are made.


Each column supports the following options that is used to specify SQL to sort data by the given column:

  • :order - an order SQL that should be used to sort by this column. Default: report column name if there is database column with this name. Passing false will disable the order for this column.
  • :order_desc - descending order expression from this column. Default: "#{order} desc".
# Basic use case
column(:group_name, :order => "") { }

# Advanced use case
  # suppose that models with null priority will be always on bottom
  :order => "priority is not null desc, priority", 
  :order_desc => "prioritty is not null desc, priority desc"
# Disable order
column(:title, :order => false)

# Order by joined table
# Allows to join specified table only when order is enabled
# for performance
column(:profile_updated_at, :order => proc { |scope|
}) do |model|

In order to specify order the following attributes are used for Datagrid instance:

  • :order - column name to sort with as Symbol. Default: nil.
  • :descending - if true descending suffix is added to specified order. Default: false. => :group, :descending => true).assets # => assets ordered by :group column descending

Default column options

You can specify default options for entire grid by using default_column_options accessor methods. They still can be overwritten at column level.

# Disable default order                           
self.default_column_options = { :order => false } 
# Makes entire report HTML                        
self.default_column_options = { :html => true }   

Columns visibility

Instance API

You are able to show only specific columns in certain context. The column_names instance accessor can be used for that:

grid = # => [["Id", "Name" "Disabled"], [1, "Allan", true], [2, "Bogdan", false]]
grid.column_names = [:id, :name] # => [["Id", "Name], [1, "Allan"], [2, "Bogdan"]]
grid.column_names = nil # Reset to default # => [["Id", "Name" "Disabled"], [1, "Allan", true], [2, "Bogdan", false]]

There is several column options that helps to control column names filter content

  • :mandatory - makes column impossible to disable. Hides it from column_names_filter selection

When you specify at least one mandatory column in a grid the column visibility mechanism become different:

  • only mandatory columns are displayed by default
  • non-mandatory columns need to be explicitly enabled by column_names attribute


class Grid
  include Datagrid
  scope { User }
  column(:id, :mandatory => true)
  column(:name, :mandatory => true)
  [:posts, :comments].each do |association|
    column(:"number_of_#{association}") do |model|

grid = # => [["Id", "Name"], [1, "Bogdan Gusiev"], [2, "Dominic Coryell"]]
grid.column_names = ["category", "number_of_posts"] # => [ ["Id", "Name", "Category", "Number of posts], 
          #      [1, "Bogdan Gusiev", "developer", 5], 
          #      [2, "Dominic Coryell", "manager", 3] ]

If and Unless options (version >= 1.1.0)

You can specify :if and :unless options to a column, to determine if the column should be shown or not. If a symbol is given, it will call that method on the grid, if a proc is given, it will be called with the grid as an argument.


column(:name, :if => :show_name?)
column(:name, :unless => proc {|grid| !grid.show_name? })
# More realistic
filter(:category) do |value|
  where("category like '%#{value}%'")
column(:exactly_match_category, :if => proc {|grid| grid.category.present?}) do |model, grid|
  model.category == grid.category

Dynamic Columns

In some cases you can not define columns at class level. So you can define columns on instance level

grid =
grid.column(:extra_data) do |model|

In this example extra_data column will not be defined for any other MyGrid instance in a project. Only for current instance stored in grid local variable.

Same behaviour can be achieved by using dynamic inside of grid class. More live example:

class CampaignsGrid
  scope { Campaign }

  filter(:account_id, :integer)

  def account

  dynamic do 
    account.sales_categories.each do |category|
      column(:"sales_in_#{}") do |campaign|

Frontend (version >= 1.0)

Column selection can be available as select[multiple] or several input[type=checkbox] in datagrid form. Use column_names_filter to reach that behavior. column_names_filter accepts same options as :enum filter.

column_names_filter(:header => "Column", :checkboxes => true)

In this case column names select will only contain counter columns. id name category columns will be always present.

You can manually specify which columns should be selectable by end user:

column_names_filter(:select => [:metric_one, :metric_two, :metric_three])

In this way you can hide columns from end user.


Column header can be specified with :header option:

column(:active, :header => "Activated")

By default it is generated from column name. Also you can use localization file if you have multilanguage application.

Example: In order to localize column :name in SimpleReport use the key

Something went wrong with that request. Please try again.