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 }
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
#available_columns ⇒ Array<Datagrid::Columns::Column>
Returns all columns that are possible to be displayed for the current grid object.
604 605 606 607 608 |
# File 'lib/datagrid/columns.rb', line 604 def available_columns columns_array.select do |column| column.enabled?(self) end end |
#batch_size ⇒ Integer
|
|
# File 'lib/datagrid/columns.rb', line 232
|
#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
|
#column(name, query = nil, **options, &block) ⇒ Object
Defines a column at instance level
577 578 579 |
# File 'lib/datagrid/columns.rb', line 577 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
529 530 531 |
# File 'lib/datagrid/columns.rb', line 529 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.
503 504 505 506 507 508 509 |
# File 'lib/datagrid/columns.rb', line 503 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.
450 451 452 |
# File 'lib/datagrid/columns.rb', line 450 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.
515 516 517 |
# File 'lib/datagrid/columns.rb', line 515 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.
467 468 469 470 471 |
# File 'lib/datagrid/columns.rb', line 467 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.
571 572 573 |
# File 'lib/datagrid/columns.rb', line 571 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.
613 614 615 616 617 618 619 620 621 |
# File 'lib/datagrid/columns.rb', line 613 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.
641 642 643 |
# File 'lib/datagrid/columns.rb', line 641 def decorate(model) self.class.decorate(model) end |
#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
|
#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
|
#format(value, &block) ⇒ Datagrid::Columns::Column::ResponseFormat
Gives ability to have a different formatting for CSV and HTML column value.
547 548 549 550 551 552 553 554 |
# File 'lib/datagrid/columns.rb', line 547 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.
430 431 432 433 434 435 436 |
# File 'lib/datagrid/columns.rb', line 430 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.
413 414 415 |
# File 'lib/datagrid/columns.rb', line 413 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.
522 523 524 |
# File 'lib/datagrid/columns.rb', line 522 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.
627 628 629 630 631 632 633 634 635 636 637 |
# File 'lib/datagrid/columns.rb', line 627 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.
421 422 423 424 425 |
# File 'lib/datagrid/columns.rb', line 421 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.
441 442 443 444 445 |
# File 'lib/datagrid/columns.rb', line 441 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.
481 482 483 484 485 486 487 488 489 490 491 492 |
# File 'lib/datagrid/columns.rb', line 481 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 |