module Symphonia module ModelAttributes class Attribute attr_reader :name, :options, :format_options, :sort_column attr_accessor :filter def initialize(name, klass, options, formatter) @name = name @klass = klass @formatter = formatter @options = options @format_options = {} end def title @klass.human_attribute_name(@name.to_s.remove(/_id$/), @options[:i18n] || {}) end def value(entity) entity.send(name) end def format(view, entity, options = {}) @format_options = options if @formatter.is_a?(Proc) @formatter.call(view, self, entity).to_s else format_value(view, value(entity), entity) end end def sort=(sort_options) t = @klass.arel_table @sort = true case sort_options when false @sort = false when Symbol, Array sort = Array(sort_options).collect { |i| t[i] } asc_desc = { asc: sort.map { |i| i.asc.to_sql }.join(','), desc: sort.map { |i| i.desc.to_sql }.join(',') } @sort_column = SortableTable::SortColumnCustomDefinition.new(@name, asc_desc) when String asc_desc = { asc: sort_options + ' ASC', desc: sort_options + ' DESC' } @sort_column = SortableTable::SortColumnCustomDefinition.new(@name, asc_desc) else raise "Undefined `sort_options` type: #{sort_options.class.name}" end end def sort? @sort end def filter? !!filter end def default? !!@options[:default] end def required? end def input_field :text_field end def input_options {} end private def format_value(_view, value, _entity) value.to_s end end class TextAttribute < Attribute def format_value(view, value, _entity) view.format_text(value) end def input_field :text_area end end class DecimalAttribute < Attribute def format_value(view, value, _entity) view.format_price(value) end end class EnumAttribute < Attribute # TODO: @klass.name || @klass.base_class.name || entity.class.name def format_value(view, value, _entity) view.t("#{@klass.name.underscore}.#{name.to_s.pluralize}.#{value}", **format_options) end def input_field :select end def input_options [] end end class LinkAttribute < Attribute def format_value(view, value, entity) view.link_to value.to_s, entity, format_options end end class MailAttribute < Attribute def format_value(view, value, _entity) view.mail_to value.to_s, value.to_s, format_options end end class ReferenceAttribute < Attribute def title if (ref = @klass.reflect_on_association(name)).macro == :belongs_to @klass.human_attribute_name(ref.foreign_key, @options[:i18n] || {}) else super end end def format_value(view, value, _entity) if value.is_a?(ActiveRecord::Associations::CollectionProxy) || value.is_a?(Array) value.collect { |v| view.link_to v.to_s, v, format_options }.join("\n").html_safe else view.link_to value.to_s, value, format_options end end def input_field nil end end class BooleanAttribute < Attribute def format_value(view, value, _entity) if value.to_boolean view.icon('true', view.t(:true)) else view.icon('false', view.t(:false)) end end def input_field :check_box end end class DateAttribute < Attribute def format_value(view, value, _entity) value && view.l(value.to_date, **format_options) end end class DateTimeAttribute < Attribute def format_value(view, value, _entity) value && view.l(value.localtime, **format_options) end end class DatetimeAttribute < DateTimeAttribute # alias end end end