Skip to content

Commit

Permalink
Move wiki into the gem
Browse files Browse the repository at this point in the history
  • Loading branch information
bogdan committed Nov 18, 2024
1 parent 9a53463 commit 8a586c5
Show file tree
Hide file tree
Showing 7 changed files with 624 additions and 38 deletions.
204 changes: 200 additions & 4 deletions lib/datagrid/columns.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,207 @@
require "active_support/core_ext/class/attribute"

module Datagrid
# Defines a column to be used for displaying data in a Datagrid.
#
# class UserGrid
# include Datagrid
#
# 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 <tt>instance_eval</tt>:
#
# 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.default_column_options = { 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
module Columns
require "datagrid/columns/column"

# @!method default_column_options=
# @param value [Hash] default options passed to #column method call
# @!method default_column_options=(value)
# @param [Hash] value default options passed to #column method call
# @return [Hash] default options passed to #column method call
# @example
# # Disable default order
Expand All @@ -20,8 +216,8 @@ module Columns
# @return [Hash]
# @see #default_column_options=

# @!method batch_size=
# @param value [Integer] Specify a default batch size when generating CSV or just data. Default: 1000
# @!method batch_size=(value)
# @param [Integer] value Specify a default batch size when generating CSV or just data. Default: 1000
# @return [Integer] Specify a default batch size when generating CSV or just data.
# @example
# self.batch_size = 500
Expand Down
22 changes: 21 additions & 1 deletion lib/datagrid/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,27 @@ def self.configure
yield(configuration)
end

# Datagrid configuration object
# == Configuration
#
# Datagrid provides several configuration options.
#
# Here is the API reference and a description of the available options:
#
# Datagrid.configure do |config|
#
# # Defines date formats that can be used to parse dates.
# # Note: Multiple formats can be specified. The first format is used to format dates as strings,
# # while other formats are used only for parsing dates from strings (e.g., if your app supports multiple formats).
# config.date_formats = ["%m/%d/%Y", "%Y-%m-%d"]
#
# # Defines timestamp formats that can be used to parse timestamps.
# # Note: Multiple formats can be specified. The first format is used to format timestamps as strings,
# # while other formats are used only for parsing timestamps from strings (e.g., if your app supports multiple formats).
# config.datetime_formats = ["%m/%d/%Y %h:%M", "%Y-%m-%d %h:%M:%s"]
#
# end
#
# These options can be set globally in your application to customize Datagrid’s behavior.
class Configuration
# @return [Array<String>] Date parsing formats
attr_accessor :date_formats
Expand Down
59 changes: 29 additions & 30 deletions lib/datagrid/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,45 @@
require "datagrid/drivers"
require "active_support/core_ext/class/attribute"
require "active_model/attribute_assignment"

module Datagrid
# ## Simple example
#
# Datagrid scope as assets source to be queried from the database.
# In most cases it is a model class with some default ORM scopes like `order` or `includes`:
# Simple example of using Datagrid scope as the assets source to be queried from the database.
#
# ``` ruby
# class ProjectsGrid
# include Datagrid
# scope { Project.includes(:category) }
# end
# ```
# In most cases, the scope is a model class with some default ORM scopes, like `order` or `includes`:
#
# Scope is also used to choose a ORM driver(Mongoid, ActiveRecord, etc.), get wether filters and columns defined below has order.
# The scope is also used to:
# - Choose an ORM driver (e.g., Mongoid, ActiveRecord, etc.).
# - Association preloading
# - Columns Providing default order
#
# You can set scope at instance level:
# You can set the scope at class level or instance level.
# Both having appropriate use cases
#
# ``` ruby
# grid = ProjectsGrid.new(grid_params) do |scope|
# scope.where(owner_id: current_user.id)
# end
# @example Defining a scope in a grid class
# class ProjectsGrid
# include Datagrid
# scope { Project.includes(:category) }
# end
#
# grid.assets # => SELECT * FROM projects WHERE projects.owner_id = ? AND [other filtering conditions]
# ```
# @example Setting a scope at the instance level
# grid = ProjectsGrid.new(grid_params) do |scope|
# scope.where(owner_id: current_user.id)
# end
#
# Scope can always be retrieved and redefined at instance level:
# grid.assets # => SELECT * FROM projects WHERE projects.owner_id = ? AND [other filtering conditions]
#
# ``` ruby
# grid.scope # => SELECT * FROM projects WHERE projects.user_id = ?
# grid.redefined_scope? # => true
# @example Retrieving and redefining the scope
# grid.scope # => SELECT * FROM projects WHERE projects.user_id = ?
# grid.redefined_scope? # => true
#
# # Reset scope to default class value
# grid.reset_scope
# grid.assets # => SELECT * FROM projects
# grid.redefined_scope? # => false
# # Reset scope to default class value
# grid.reset_scope
# grid.assets # => SELECT * FROM projects
# grid.redefined_scope? # => false
#
# # Overwriting the scope (ignore previously defined)
# grid.scope { current_user.projects }
# grid.redefined_scope? # => true
# ```
# # Overwriting the scope (ignoring previously defined)
# grid.scope { current_user.projects }
# grid.redefined_scope? # => true
module Core
include ::ActiveModel::AttributeAssignment

Expand Down
2 changes: 1 addition & 1 deletion lib/datagrid/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
require "datagrid/form_builder"

module Datagrid
# @!private
# @!visibility private
class Engine < ::Rails::Engine
def self.extend_modules
ActionView::Base.include(Datagrid::Helper)
Expand Down
Loading

0 comments on commit 8a586c5

Please sign in to comment.