Module: Datagrid::Columns
Overview
Defines a column to be used for displaying data in a Datagrid.
class UserGrid < ApplicationGrid
scope do
User.order("users.created_at desc").joins(:group)
end
column(:name)
column(:group, order: "groups.name") do
self.group.name
end
column(:active, header: "Activated") do |user|
!user.disabled
end
end
Each column is used to generate data for the grid.
To create a grid displaying all users:
grid = UserGrid.new
grid.header # => ["Group", "Name", "Disabled"]
grid.rows # => [
# ["Steve", "Spammers", true],
# ["John", "Spoilers", true],
# ["Berry", "Good people", false]
# ]
grid.data # => Header & Rows
grid.data_hash # => [
# { name: "Steve", group: "Spammers", active: true },
# { name: "John", group: "Spoilers", active: true },
# { name: "Berry", group: "Good people", active: false },
# ]
}
Column Value
The value of a column can be defined by passing a block to Datagrid.column
.
Basic Column Value
If no block is provided, the column value is generated automatically by sending the column name method to the model.
column(:name) # => asset.name
Using instance_eval:
column(:completed) { completed? }
Using the asset as an argument:
column(:completed) { |asset| asset.completed? }
Advanced Column Value
You can also pass the Datagrid object itself to define more complex column values.
Using filters with columns:
filter(:category) do |value|
where("category LIKE '%#{value}%'")
end
column(:exactly_matches_category) do |asset, grid|
asset.category == grid.category
end
Combining columns:
column(:total_sales) do |merchant|
merchant.purchases.sum(:subtotal)
end
column(:number_of_sales) do |merchant|
merchant.purchases.count
end
column(:average_order_value) do |_, _, row|
row.total_sales / row.number_of_sales
end
Using Database Expressions
Columns can use database expressions to directly manipulate data in the database.
column(:count_of_users, 'count(user_id)')
column(:uppercase_name, 'upper(name)')
HTML Columns
Columns can have different formats for HTML and non-HTML representations.
column(:name) do |asset|
format(asset.name) do |value|
content_tag(:strong, value)
end
end
Column Value Cache
Enables grid-level caching for column values.
self.cached = true
Ordering
Columns can specify SQL ordering expressions using the :order
and :order_desc
options.
Basic ordering:
column(:group_name, order: "groups.name") { self.group.name }
In example above descending order is automatically inherited from ascending order specified. When such default is not enough, specify both options together:
column(
:priority,
# models with null priority are always on bottom
# no matter if sorting ascending or descending
order: "priority is not null desc, priority",
order_desc: "priority is not null desc, priority desc"
)
Disable order like this:
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|
scope.joins(:profile).order("profiles.updated_at")
}) do |model|
model.profile.updated_at.to_date
end
Order by a calculated value
column(
:duration_request,
order: "(requests.finished_at - requests.accepted_at)"
) do |model|
Time.at(model.finished_at - model.accepted_at).strftime("%H:%M:%S")
end
Default Column Options
Default options for all columns in a grid can be set using default_column_options
.
self. = { order: false }
It can also accept a proc with the column instance as an argument:
self. = ->(column) { { order: column.name == :id } }
Columns Visibility
Columns can be dynamically shown or hidden based on the grid's column_names
accessor.
grid.column_names = [:id, :name]
Dynamic Columns
Columns can be defined dynamically on a grid instance or based on data.
Adding a dynamic column:
grid.column(:extra_data) do |model|
model.extra_data
end
Localization
Column headers can be localized using the :header
option or through i18n files.
column(:active, header: Proc.new { I18n.t("activated") })
Preloading Associations
Preload database associations for better performance.
Automatic association preloading:
column(:group) do |user|
user.group.name
end
Custom preloading:
column(:account_name, preload: { |s| s.includes(:account) })
Decorator
A decorator or presenter class can be used around each object in the scope
.
decorate { UserPresenter }
column(:created_at) do |presenter|
presenter.user.created_at
end
Defined Under Namespace
Modules: ClassMethods Classes: Column, DataRow
Instance Method Summary collapse
-
#available_columns ⇒ Array<Datagrid::Columns::Column>
All columns that are possible to be displayed for the current grid object.
- #batch_size ⇒ Integer
-
#batch_size=(value) ⇒ void
Specify a default batch size when generating CSV or just data.
-
#column(name, query = nil, **options, &block) ⇒ Object
Defines a column at instance level.
-
#column_by_name(name) ⇒ Datagrid::Columns::Column?
Finds a column by name.
-
#columns(*column_names, data: false, html: false) ⇒ Array<Datagrid::Columns::Column>
All columns selected in grid instance.
-
#data(*column_names) ⇒ Array<Array<Object>>
Data for each row in datagrid assets with header.
-
#data_columns(*column_names, html: false) ⇒ Array<Datagrid::Columns::Column>
Columns that can be represented in plain data(non-html) way.
-
#data_hash ⇒ Array<Hash{Symbol => Object}>
An array of hashes representing the rows in the filtered datagrid relation.
-
#data_row(asset) ⇒ Datagrid::Columns::DataRow
An object representing a grid row.
-
#data_value(column_name, asset) ⇒ Object
A cell data value for given column name and asset.
-
#decorate(model) ⇒ Object
A decorated version of given model if decorator is specified or the model otherwise.
-
#default_column_options ⇒ Hash, Proc
Default options passed to #column method call, or a proc that returns them.
-
#default_column_options=(value) ⇒ Hash, Proc
Default options passed to #column method call, or a proc that returns them.
-
#format(value, &block) ⇒ Datagrid::Columns::Column::ResponseFormat
Gives ability to have a different formatting for CSV and HTML column value.
-
#hash_for(asset) ⇒ Hash
A mapping where keys are column names and values are column values for the given asset.
-
#header(*column_names) ⇒ Array<String>
Human readable column names.
-
#html_columns(*column_names, data: false) ⇒ Object
All columns that can be represented in HTML table.
-
#html_value(column_name, context, asset) ⇒ Object
A cell HTML value for given column name and asset and view context.
-
#row_for(asset, *column_names) ⇒ Array<Object>
Column values for given asset.
-
#rows(*column_names) ⇒ Array<Array<Object>>
With data for each row in datagrid assets without header.
-
#to_csv(*column_names, **options) ⇒ String
A CSV representation of the data in the grid.
Instance Method Details
permalink #available_columns ⇒ Array<Datagrid::Columns::Column>
Returns all columns that are possible to be displayed for the current grid object.
601 602 603 604 605 |
# File 'lib/datagrid/columns.rb', line 601 def available_columns columns_array.select do |column| column.enabled?(self) end end |
permalink #batch_size=(value) ⇒ void
This method returns an undefined value.
Specify a default batch size when generating CSV or just data.
|
# File 'lib/datagrid/columns.rb', line 223
|
permalink #column(name, query = nil, **options, &block) ⇒ Object
Defines a column at instance level
574 575 576 |
# File 'lib/datagrid/columns.rb', line 574 def column(name, query = nil, **, &block) self.class.define_column(columns_array, name, query, **, &block) end |
permalink #column_by_name(name) ⇒ Datagrid::Columns::Column?
Finds a column by name
526 527 528 |
# File 'lib/datagrid/columns.rb', line 526 def column_by_name(name) self.class.find_column_by_name(columns_array, name) end |
permalink #columns(*column_names, data: false, html: false) ⇒ Array<Datagrid::Columns::Column>
Returns all columns selected in grid instance.
500 501 502 503 504 505 506 |
# File 'lib/datagrid/columns.rb', line 500 def columns(*column_names, data: false, html: false) self.class.filter_columns( columns_array, *column_names, data: data, html: html, ).select do |column| column.enabled?(self) end end |
permalink #data(*column_names) ⇒ Array<Array<Object>>
Returns data for each row in datagrid assets with header.
447 448 449 |
# File 'lib/datagrid/columns.rb', line 447 def data(*column_names) rows(*column_names).unshift(header(*column_names)) end |
permalink #data_columns(*column_names, html: false) ⇒ Array<Datagrid::Columns::Column>
Returns columns that can be represented in plain data(non-html) way.
512 513 514 |
# File 'lib/datagrid/columns.rb', line 512 def data_columns(*column_names, html: false) columns(*column_names, html: html, data: true) end |
permalink #data_hash ⇒ Array<Hash{Symbol => Object}>
Returns an array of hashes representing the rows in the filtered datagrid relation.
464 465 466 467 468 |
# File 'lib/datagrid/columns.rb', line 464 def data_hash map_with_batches do |asset| hash_for(asset) end end |
permalink #data_row(asset) ⇒ Datagrid::Columns::DataRow
Returns an object representing a grid row.
568 569 570 |
# File 'lib/datagrid/columns.rb', line 568 def data_row(asset) ::Datagrid::Columns::DataRow.new(self, asset) end |
permalink #data_value(column_name, asset) ⇒ Object
Returns a cell data value for given column name and asset.
610 611 612 613 614 615 616 617 618 |
# File 'lib/datagrid/columns.rb', line 610 def data_value(column_name, asset) column = column_by_name(column_name) cache(column, asset, :data_value) do raise "no data value for #{column.name} column" unless column.data? result = generic_value(column, asset) result.is_a?(Datagrid::Columns::Column::ResponseFormat) ? result.call_data : result end end |
permalink #decorate(model) ⇒ Object
Returns a decorated version of given model if decorator is specified or the model otherwise.
638 639 640 |
# File 'lib/datagrid/columns.rb', line 638 def decorate(model) self.class.decorate(model) end |
permalink #default_column_options ⇒ Hash, Proc
Returns default options passed to #column method call, or a proc that returns them.
|
# File 'lib/datagrid/columns.rb', line 219
|
permalink #default_column_options=(value) ⇒ Hash, Proc
Returns default options passed to #column method call, or a proc that returns them.
|
# File 'lib/datagrid/columns.rb', line 207
|
permalink #format(value, &block) ⇒ Datagrid::Columns::Column::ResponseFormat
Gives ability to have a different formatting for CSV and HTML column value.
544 545 546 547 548 549 550 551 |
# File 'lib/datagrid/columns.rb', line 544 def format(value, &block) if block self.class.format(value, &block) else # don't override Object#format method super end end |
permalink #hash_for(asset) ⇒ Hash
Returns A mapping where keys are column names and values are column values for the given asset.
427 428 429 430 431 432 433 |
# File 'lib/datagrid/columns.rb', line 427 def hash_for(asset) result = {} data_columns.each do |column| result[column.name] = data_value(column, asset) end result end |
permalink #header(*column_names) ⇒ Array<String>
Returns human readable column names. See also "Localization" section.
410 411 412 |
# File 'lib/datagrid/columns.rb', line 410 def header(*column_names) data_columns(*column_names).map(&:header) end |
permalink #html_columns(*column_names, data: false) ⇒ Object
Returns all columns that can be represented in HTML table.
519 520 521 |
# File 'lib/datagrid/columns.rb', line 519 def html_columns(*column_names, data: false) columns(*column_names, data: data, html: true) end |
permalink #html_value(column_name, context, asset) ⇒ Object
Returns a cell HTML value for given column name and asset and view context.
624 625 626 627 628 629 630 631 632 633 634 |
# File 'lib/datagrid/columns.rb', line 624 def html_value(column_name, context, asset) column = column_by_name(column_name) cache(column, asset, :html_value) do if column.html? && column.html_block value_from_html_block(context, asset, column) else result = generic_value(column, asset) result.is_a?(Datagrid::Columns::Column::ResponseFormat) ? result.call_html(context) : result end end end |
permalink #row_for(asset, *column_names) ⇒ Array<Object>
Returns column values for given asset.
418 419 420 421 422 |
# File 'lib/datagrid/columns.rb', line 418 def row_for(asset, *column_names) data_columns(*column_names).map do |column| data_value(column, asset) end end |
permalink #rows(*column_names) ⇒ Array<Array<Object>>
Returns with data for each row in datagrid assets without header.
438 439 440 441 442 |
# File 'lib/datagrid/columns.rb', line 438 def rows(*column_names) map_with_batches do |asset| row_for(asset, *column_names) end end |
permalink #to_csv(*column_names, **options) ⇒ String
Returns a CSV representation of the data in the grid.
478 479 480 481 482 483 484 485 486 487 488 489 |
# File 'lib/datagrid/columns.rb', line 478 def to_csv(*column_names, **) require "csv" CSV.generate( headers: header(*column_names), write_headers: true, **, ) do |csv| each_with_batches do |asset| csv << row_for(asset, *column_names) end end end |