metaminded/tabulatr2

View on GitHub
lib/tabulatr/renderer/column.rb

Summary

Maintainability
A
0 mins
Test Coverage
#--
# Copyright (c) 2010-2014 Peter Horn & Florian Thomas, metaminded UG
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#++

class Tabulatr::Renderer::Column
  include ActiveModel::Model

  attr_accessor *%i{name klass table_name col_options output block}

  delegate :filter, to: :col_options

  def self.from(
    name: nil,
    table_name: nil,
    col_options: nil,
    klass: nil,
    output: nil,
    &block)
    self.new(
      name: name,
      table_name: table_name,
      col_options: col_options,
      klass: klass,
      output: output,
      block: block
    )
  end

  def klassname() @_klassname ||= @klass.name.underscore end

  def human_name()
    h = col_options.header
    if h && h.respond_to?(:call)
      h.()
    elsif h
      h
    else
      klass.human_attribute_name(name)
    end
  end

  def sort_param() "#{klassname}_sort" end
  def full_name() [table_name, name].compact.join(":") end
  def coltype() 'column' end

  def column?() true end
  def association?() false end
  def checkbox?() false end
  def action?() false end

  def value_for(record, view)
    val = principal_value(record, view)
    if self.col_options.format.present?
      if val.respond_to?(:to_ary)
        val.map do |v|
          format_value(v, view)
        end
      else
        format_value(val, view)
      end
    else
      val
    end
  end

  def principal_value(record, view)
    if output
      view.instance_exec(record, &output)
    elsif block
      view.instance_exec(record, &block)
    elsif name
      record.send name
    else
      nil
    end
  end

  def determine_appropriate_filter!
    typ = self.klass.columns_hash[self.name.to_s].type.to_sym rescue nil
    case typ
    when :integer then self.col_options.filter = filter_type_for_integer
    when :enum then self.col_options.filter = :enum
    when :float, :decimal then self.col_options.filter = :decimal
    when :string, :text then self.col_options.filter = :like
    when :date, :time, :datetime, :timestamp then self.col_options.filter = :date
    when :boolean then self.col_options.filter = :checkbox
    when nil then self.col_options.filter = :exact
    else raise "Unknown filter type for #{self.name}: »#{typ}«"
    end
  end

  def to_json
    {
      name:        "#{table_name}:#{name}",
      # name:        name,
      header:      human_name,
      # klassname:   klassname,
      # table_name:  table_name,
      filter:      col_options.filter,
      sortable:    col_options.sortable,
      data_html:   col_options.data_html,
      header_html: col_options.header_html,
    }
  end

  private

  def filter_type_for_integer
    if self.klass.respond_to?(:defined_enums) && self.klass.defined_enums.keys.include?(self.name.to_s)
      :enum
    else
      :integer
    end
  end

  def format_value(value, view)
    case self.col_options.format
    when Symbol then view.send(col_options.format, value)
    when String then col_options.format % value
    when Proc   then col_options.format.(value)
    else value
    end
  end

end