Module: Datagrid::Columns
- Included in:
- Base
- Defined in:
- lib/datagrid/columns.rb,
lib/datagrid/columns/column.rb
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 }
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
Default options passed to #column method call.
-
#default_column_options=(value) ⇒ Hash
Default options passed to #column method call.
-
#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
#available_columns ⇒ Array<Datagrid::Columns::Column>
Returns all columns that are possible to be displayed for the current grid object.
592 593 594 595 596 |
# File 'lib/datagrid/columns.rb', line 592 def available_columns columns_array.select do |column| column.enabled?(self) end end |
#batch_size ⇒ Integer
|
# File 'lib/datagrid/columns.rb', line 224
|
#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 215
|
#column(name, query = nil, **options, &block) ⇒ Object
Defines a column at instance level
565 566 567 |
# File 'lib/datagrid/columns.rb', line 565 def column(name, query = nil, **, &block) self.class.define_column(columns_array, name, query, **, &block) end |
#column_by_name(name) ⇒ Datagrid::Columns::Column?
Finds a column by name
517 518 519 |
# File 'lib/datagrid/columns.rb', line 517 def column_by_name(name) self.class.find_column_by_name(columns_array, name) end |
#columns(*column_names, data: false, html: false) ⇒ Array<Datagrid::Columns::Column>
Returns all columns selected in grid instance.
491 492 493 494 495 496 497 |
# File 'lib/datagrid/columns.rb', line 491 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 |
#data(*column_names) ⇒ Array<Array<Object>>
Returns data for each row in datagrid assets with header.
438 439 440 |
# File 'lib/datagrid/columns.rb', line 438 def data(*column_names) rows(*column_names).unshift(header(*column_names)) end |
#data_columns(*column_names, html: false) ⇒ Array<Datagrid::Columns::Column>
Returns columns that can be represented in plain data(non-html) way.
503 504 505 |
# File 'lib/datagrid/columns.rb', line 503 def data_columns(*column_names, html: false) columns(*column_names, html: html, data: true) end |
#data_hash ⇒ Array<Hash{Symbol => Object}>
Returns an array of hashes representing the rows in the filtered datagrid relation.
455 456 457 458 459 |
# File 'lib/datagrid/columns.rb', line 455 def data_hash map_with_batches do |asset| hash_for(asset) end end |
#data_row(asset) ⇒ Datagrid::Columns::DataRow
Returns an object representing a grid row.
559 560 561 |
# File 'lib/datagrid/columns.rb', line 559 def data_row(asset) ::Datagrid::Columns::DataRow.new(self, asset) end |
#data_value(column_name, asset) ⇒ Object
Returns a cell data value for given column name and asset.
601 602 603 604 605 606 607 608 609 |
# File 'lib/datagrid/columns.rb', line 601 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 |
#decorate(model) ⇒ Object
Returns a decorated version of given model if decorator is specified or the model otherwise.
629 630 631 |
# File 'lib/datagrid/columns.rb', line 629 def decorate(model) self.class.decorate(model) end |
#default_column_options ⇒ Hash
Returns default options passed to #column method call.
|
# File 'lib/datagrid/columns.rb', line 211
|
#default_column_options=(value) ⇒ Hash
Returns default options passed to #column method call.
|
# File 'lib/datagrid/columns.rb', line 203
|
#format(value, &block) ⇒ Datagrid::Columns::Column::ResponseFormat
Gives ability to have a different formatting for CSV and HTML column value.
535 536 537 538 539 540 541 542 |
# File 'lib/datagrid/columns.rb', line 535 def format(value, &block) if block self.class.format(value, &block) else # don't override Object#format method super end end |
#hash_for(asset) ⇒ Hash
Returns A mapping where keys are column names and values are column values for the given asset.
418 419 420 421 422 423 424 |
# File 'lib/datagrid/columns.rb', line 418 def hash_for(asset) result = {} data_columns.each do |column| result[column.name] = data_value(column, asset) end result end |
#header(*column_names) ⇒ Array<String>
Returns human readable column names. See also "Localization" section.
401 402 403 |
# File 'lib/datagrid/columns.rb', line 401 def header(*column_names) data_columns(*column_names).map(&:header) end |
#html_columns(*column_names, data: false) ⇒ Object
Returns all columns that can be represented in HTML table.
510 511 512 |
# File 'lib/datagrid/columns.rb', line 510 def html_columns(*column_names, data: false) columns(*column_names, data: data, html: true) end |
#html_value(column_name, context, asset) ⇒ Object
Returns a cell HTML value for given column name and asset and view context.
615 616 617 618 619 620 621 622 623 624 625 |
# File 'lib/datagrid/columns.rb', line 615 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 |
#row_for(asset, *column_names) ⇒ Array<Object>
Returns column values for given asset.
409 410 411 412 413 |
# File 'lib/datagrid/columns.rb', line 409 def row_for(asset, *column_names) data_columns(*column_names).map do |column| data_value(column, asset) end end |
#rows(*column_names) ⇒ Array<Array<Object>>
Returns with data for each row in datagrid assets without header.
429 430 431 432 433 |
# File 'lib/datagrid/columns.rb', line 429 def rows(*column_names) map_with_batches do |asset| row_for(asset, *column_names) end end |
#to_csv(*column_names, **options) ⇒ String
Returns a CSV representation of the data in the grid.
469 470 471 472 473 474 475 476 477 478 479 480 |
# File 'lib/datagrid/columns.rb', line 469 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 |