class TrkDatatables::ColumnKeyOptions

Constants

BOOLEAN_CALCULATED_IN_DB
CLASS_NAME
COLUMN_OPTIONS

this will load date picker SEARCH_OPTION_DATE_VALUE = :date SEARCH_OPTION_DATETIME_VALUE = :datetime

COLUMN_TYPE_IN_DB
DATETIME_CALCULATED_IN_DB
DATE_CALCULATED_IN_DB
DB_ADAPTER_STRING_TYPE_CAST
HIDE_OPTION
INTEGER_CALCULATED_IN_DB
ORDER_OPTION
PREDEFINED_RANGES
SEARCH_OPTION
SELECT_OPTIONS
STRING_CALCULATED_IN_DB

for columns that as calculated in db query

STRING_TYPE_CAST_MYSQL
STRING_TYPE_CAST_ORACLE
STRING_TYPE_CAST_POSTGRES

for 'columns' that are calculated in Ruby you need to disable search and order and than it will not be used in queries

STRING_TYPE_CAST_SQLITE
TITLE_OPTION

All options that you can use for columns:

search: if you want to enable global and column search, default is true order: `:asc` or `:desc` or `false`, default is `:desc` @code

def columns
  {
    'users.name': { search: false }
  }

Attributes

string_cast[RW]

Public Class Methods

new(cols, global_search_cols, predefined_ranges = {}) click to toggle source

@return

{
  column_key: :'users.name',
  column_options: { order: false, select_options: User.statuses },
  table_class: User,
  column_name: :name,
  column_type_in_db: :string,
  title: 'Name',
  html_options: { class: 'my-class' },
}
# File lib/trk_datatables/column_key_options.rb, line 85
def initialize(cols, global_search_cols, predefined_ranges = {})
  @predefined_ranges = predefined_ranges
  # short notation is when we use array of keys.
  # In case first element is hash than we will use that hash
  if cols.is_a? Array
    cols = if cols.first.is_a? Hash
             cols.first
           else
             cols.each_with_object({}) do |column_key, hash|
               hash[column_key.to_sym] = {}
             end
           end
  end
  _set_data(cols)
  _set_global_search_cols(global_search_cols)
  @string_cast = _determine_string_type_cast
end

Public Instance Methods

[](index) click to toggle source
# File lib/trk_datatables/column_key_options.rb, line 220
def [](index)
  raise Error, "You asked for column index=#{index} but there is only #{@data.size} columns" if index >= @data.size

  @data[index]
end
_determine_column_name(table_class, column_name) click to toggle source
# File lib/trk_datatables/column_key_options.rb, line 203
def _determine_column_name(table_class, column_name)
  return column_name.titleize if table_class.blank?

  # maybe we should check if human_attribute_name exists
  table_class.human_attribute_name column_name
end
_determine_db_type_for_column(table_class, column_name) click to toggle source

@return

:string, :integer, :date, :datetime
# File lib/trk_datatables/column_key_options.rb, line 188
def _determine_db_type_for_column(table_class, column_name)
  if table_class < TrkDatatables::CalculatedInDb
    table_class.determine_db_type_for_column
  elsif defined?(::ActiveRecord::Base)
    ar_column = table_class.columns_hash[column_name]
    raise Error, "Can't find column #{column_name} in #{table_class.name}" unless ar_column

    ar_column.type
  elsif defined?(::Neo4j::ActiveNode)
    (table_class.declared_properties[column_name][:type] || String).name.downcase
  else
    raise NotImplementedError, 'I work only with ActiveRecord and Neo4j'
  end
end
_determine_table_class(table_name, class_name = nil) click to toggle source
# File lib/trk_datatables/column_key_options.rb, line 140
def _determine_table_class(table_name, class_name = nil)
  # post_users -> PostUser
  # but also check if admin_posts -> Admin::Post so user can defined
  # class_name: 'Admin::Post'
  # https://github.com/duleorlovic/rails/blob/master/activesupport/lib/active_support/inflector/methods.rb#L289
  # note that when class is not eager loaded than const_defined? returns false
  if class_name.present?
    class_name.constantize
  elsif table_name.ends_with? '_calculated_in_db'
    "TrkDatatables::#{table_name.classify}".constantize
  else
    table_name.classify.constantize
  end
end
_set_data(cols) click to toggle source
# File lib/trk_datatables/column_key_options.rb, line 103
def _set_data(cols)
  @data = cols.each_with_object([]) do |(column_key, column_options), arr|
    raise Error, 'Column options needs to be a Hash' unless column_options.is_a? Hash

    column_options.assert_valid_keys(*COLUMN_OPTIONS)
    table_name, column_name = column_key.to_s.split '.'
    if table_name.present? && table_name.ends_with?('_calculated_in_db')
      # in calculated columns table_name is used only to determine type
      column_key = column_name
    elsif table_name.present? && column_name.nil?
      raise Error, 'Unless table name ends with _calculated_in_db, column key needs to have one dot for example: posts.name'
    end

    if table_name.blank?
      column_name = column_options[TITLE_OPTION] || 'actions' # some default name for a title
      column_options[SEARCH_OPTION] = false
      column_options[ORDER_OPTION] = false
    else
      table_class = _determine_table_class table_name, column_options[CLASS_NAME]

      unless column_options[SEARCH_OPTION] == false && column_options[ORDER_OPTION] == false
        column_type_in_db = column_options[COLUMN_TYPE_IN_DB] || _determine_db_type_for_column(table_class, column_name)
      end
    end
    arr << {
      column_key: column_key.to_sym,
      column_options: column_options,
      table_class: table_class,
      column_name: column_name,
      column_type_in_db: column_type_in_db,
      # the following are used for RenderHtml
      title: column_options[TITLE_OPTION] || _determine_column_name(table_class, column_name),
      html_options: html_options(column_options, column_type_in_db),
    }
  end
end
_set_global_search_cols(global_search_cols) click to toggle source
# File lib/trk_datatables/column_key_options.rb, line 155
def _set_global_search_cols(global_search_cols)
  raise Error, 'global_search_cols should be array, for example %w[users.name]' unless global_search_cols.is_a? Array

  @global_search_cols = global_search_cols.each_with_object([]) do |column_key, arr|
    table_name, column_name = column_key.to_s.split '.'
    table_class = _determine_table_class table_name
    column_type_in_db = _determine_db_type_for_column(table_class, column_name)
    arr << {
      column_key: column_key.to_sym,
      column_options: {},
      table_class: table_class,
      column_name: column_name,
      column_type_in_db: column_type_in_db,
    }
  end
end
each(&block) click to toggle source
# File lib/trk_datatables/column_key_options.rb, line 226
def each(&block)
  @data.each(&block)
end
html_options(column_options, column_type_in_db) click to toggle source
# File lib/trk_datatables/column_key_options.rb, line 243
def html_options(column_options, column_type_in_db)
  res = {}
  res['data-searchable'] = false if column_options[SEARCH_OPTION] == false
  res['data-orderable'] = false if column_options[ORDER_OPTION] == false
  res['data-datatable-hidden-column'] = true if column_options[HIDE_OPTION] == true
  res['data-datatable-checkbox'] = true if column_type_in_db == :boolean
  if %i[date datetime].include? column_type_in_db
    res['data-datatable-range'] = column_type_in_db == :datetime ? :datetime : true
    if column_options[PREDEFINED_RANGES].present? ||
        (@predefined_ranges.try(:[], column_type_in_db).present? && column_options[PREDEFINED_RANGES] != false)
      res['data-datatable-predefined-ranges'] = if column_options[PREDEFINED_RANGES].is_a? Hash
                                                  column_options[PREDEFINED_RANGES]
                                                else
                                                  @predefined_ranges[column_type_in_db]
                                                end
      res['data-datatable-predefined-ranges'].transform_values! do |range|
        [range.first.to_s, range.last.to_s]
      end
    end
  end
  res
end
index_by_column_key(column_key) click to toggle source
# File lib/trk_datatables/column_key_options.rb, line 234
def index_by_column_key(column_key)
  i = @data.find_index do |column_key_option|
    column_key_option[:column_key] == column_key.to_sym
  end
  raise Error, "Can't find index for #{column_key} in #{@data.map { |d| d[:column_key] }.join(', ')}" if i.nil?

  i
end
searchable() click to toggle source
# File lib/trk_datatables/column_key_options.rb, line 210
def searchable
  @data.reject do |column_key_option|
    column_key_option[:column_options][SEARCH_OPTION] == false
  end
end
size() click to toggle source
# File lib/trk_datatables/column_key_options.rb, line 230
def size
  @data.size
end