require 'active_record' require 'cgi' require_relative 'expressions' module RailsServersideDatatables class Column CONFIGURATION_KEYS = [ :display_name, :column_filtering, :sorting, :filtering ] attr_accessor :decorator attr_accessor :display_name, :column_filtering, :sorting, :filtering def initialize( name, definition, config = {}, &block ) @name = name @definition = ExprTreeNode.create_by_type definition @structured = config.reject { |c| CONFIGURATION_KEYS.include? c }.to_a.map { |s| [s.first, ExprTreeNode.create_by_type(s.last ) ] }.to_h @decorator = block @display_name = config.fetch( :display_name, name.to_s.capitalize ) @column_filtering = config.fetch( :column_filtering, true ) @sorting = config.fetch( :sorting, true ) @filtering = config.fetch( :filtering, true ) end def order_definition=( definition ) @order_definition = definition end def structured( record ) @structured.to_a.map do |s| [s.first, record.read_attribute(helper_column_name s.first)] end.to_h end def value( record ) decorated record.read_attribute( main_column_name ), structured( record ) end def select @structured.to_a.map { |c| ExpressionAlias.new( c.last, helper_column_name(c.first) ) } + [ ExpressionAlias.new( @definition, main_column_name ) ] end def order( direction = :ASC ) return Nothing.new unless sorting OrderBy.new( @order_definition || main_column_name, direction ) end def column_filter( filter ) return Nothing.new unless column_filtering create_filter( filter ) end def filter( filter ) return Nothing.new unless filtering create_filter( filter ) end def configuration { filtering: filtering, sorting: sorting, column_filtering: true, display_name: display_name, name: @name } end private def create_filter( filter ) FilterByText.new( @definition, filter ) end def decorated( main, structured ) @decorator.nil? ? CGI.escapeHTML( main.to_s ) : @decorator.call( main, structured ) end def main_column_name "#{@name.to_s}_main".to_sym end def helper_column_name( structured_label ) "#{@name.to_s}_raw_#{structured_label.to_s}".to_sym end end end