# Fat Free CRM # Copyright (C) 2008-2011 by Michael Dvorkin # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . #------------------------------------------------------------------------------ # == Schema Information # # Table name: fields # # id :integer not null, primary key # type :string(255) # field_group_id :integer # position :integer # pair_id :integer # name :string(64) # label :string(128) # hint :string(255) # placeholder :string(255) # as :string(32) # collection :text # disabled :boolean # required :boolean # maxlength :integer # created_at :datetime # updated_at :datetime # class Field < ActiveRecord::Base acts_as_list serialize :collection, Array serialize :settings, HashWithIndifferentAccess belongs_to :field_group scope :core_fields, where(:type => 'CoreField') scope :custom_fields, where("type != 'CoreField'") scope :without_pairs, where(:pair_id => nil) delegate :klass, :klass_name, :klass_name=, :to => :field_group BASE_FIELD_TYPES = { 'string' => {:klass => 'CustomField', :type => 'string'}, 'text' => {:klass => 'CustomField', :type => 'text'}, 'email' => {:klass => 'CustomField', :type => 'string'}, 'url' => {:klass => 'CustomField', :type => 'string'}, 'tel' => {:klass => 'CustomField', :type => 'string'}, 'select' => {:klass => 'CustomField', :type => 'string'}, 'radio' => {:klass => 'CustomField', :type => 'string'}, 'check_boxes' => {:klass => 'CustomField', :type => 'text'}, 'boolean' => {:klass => 'CustomField', :type => 'boolean'}, 'date' => {:klass => 'CustomField', :type => 'date'}, 'datetime' => {:klass => 'CustomField', :type => 'timestamp'}, 'decimal' => {:klass => 'CustomField', :type => 'decimal', :column_options => {:precision => 15, :scale => 2} }, 'integer' => {:klass => 'CustomField', :type => 'integer'}, 'float' => {:klass => 'CustomField', :type => 'float'} }.with_indifferent_access validates_presence_of :label, :message => "^Please enter a field label." validates_length_of :label, :maximum => 64, :message => "^The field name must be less than 64 characters in length." validates_numericality_of :maxlength, :only_integer => true, :allow_blank => true, :message => "^Max size can only be whole number." validates_presence_of :as, :message => "^Please specify a field type." validates_inclusion_of :as, :in => Proc.new{self.field_types.keys}, :message => "^Invalid field type.", :allow_blank => true def column_type(field_type = self.as) (opts = Field.field_types[field_type]) ? opts[:type] : raise("Unknown field_type: #{field_type}") end def input_options input_html = {} attributes.reject { |k,v| !%w(as collection disabled label placeholder required maxlength).include?(k) or v.blank? }.symbolize_keys.merge(input_html) end def collection_string=(value) self.collection = value.split("|").map(&:strip).reject(&:blank?) end def collection_string collection.try(:join, "|") end def render_value(object) render object.send(name) end def render(value) case as when 'checkbox' value.to_s == '0' ? "no" : "yes" when 'date' value && value.strftime(I18n.t("date.formats.mmddyy")) when 'datetime' value && value.strftime(I18n.t("time.formats.mmddyyyy_hhmm")) when 'check_boxes' value.select(&:present?).in_groups_of(2, false).map {|g| g.join(', ')}.join("
".html_safe) if Array === value else value.to_s end end protected class << self # Provides access to registered field_types #------------------------------------------------------------------------------ def field_types @@field_types ||= BASE_FIELD_TYPES end # Register custom fields so they are available to the rest of the app # Example options: :as => 'datepair', :type => 'date', :klass => 'CustomFieldDatePair' #------------------------------------------------------------------------------ def register(options) opts = options.dup as = options.delete(:as) (@@field_types ||= BASE_FIELD_TYPES).merge!(as => options) end # Returns class name given a key #------------------------------------------------------------------------------ def lookup_class(as) (@@field_types ||= BASE_FIELD_TYPES)[as][:klass] end end end