app/models/field.rb
class Field
include CouchRest::Model::CastedModel
include RapidFTR::Model
include PropertiesLocalization
# track down whether the instance is new or not.
# CouchRest::Model::Embeddable new? method rely
# on the new? of the parent object. This make not
# possible to know if the embedded item already
# exists or not in the database. The parent object
# is responsible to set the flag.
# document_saved nil or false consider the field as new.
# TODO: move to a monkey patch for CouchRest::Model::Embeddable
attr_accessor :document_saved
property :name
property :visible, TrueClass, :default => true
property :matchable, TrueClass, :default => false
property :title_field, TrueClass, :default => false
property :type
property :highlight_information, HighlightInformation
property :editable, TrueClass, :default => true
localize_properties [:display_name, :help_text, :option_strings_text]
attr_reader :options
property :base_language, :default => 'en'
FIELD_TYPES = [
TEXT_FIELD = 'text_field',
TEXT_AREA = 'textarea',
RADIO_BUTTON = 'radio_button',
SELECT_BOX = 'select_box',
CHECK_BOXES = 'check_boxes',
NUMERIC_FIELD = 'numeric_field',
PHOTO_UPLOAD_BOX = 'photo_upload_box',
AUDIO_UPLOAD_BOX = 'audio_upload_box',
DATE_FIELD = 'date_field'
]
validates "display_name_#{I18n.default_locale}", :presence => {:message => I18n.t('errors.models.field.display_name_presence')}
validate :validate_unique_name
validate :validate_has_2_options
validate :validate_has_a_option
validate :validate_name_format
validate :valid_presence_of_base_language_name
def validate_name_format
special_characters = /[*!@#%$\^]/
white_spaces = /^(\s+)$/
if (display_name =~ special_characters) || (display_name =~ white_spaces)
errors.add(:display_name, I18n.t('errors.models.field.display_name_format'))
return false
else
return true
end
end
def valid_presence_of_base_language_name
if base_language.nil?
self.base_language = 'en'
end
base_lang_display_name = send("display_name_#{base_language}")
if base_lang_display_name.nil? || base_lang_display_name.empty?
errors.add(:display_name, I18n.t('errors.models.form_section.presence_of_base_language_name', :base_language => base_language))
end
end
# Override new? method to not rely on the new? of the parent object.
# TODO: move to a monkey patch for CouchRest::Model::Embeddable
def new?
!@document_saved
end
alias_method :new_record?, :new?
def form
base_doc
end
def display_type
case type
when PHOTO_UPLOAD_BOX then 'photo'
when AUDIO_UPLOAD_BOX then 'audio'
else 'basic'
end
end
def display_name_for_field_selector
hidden_text = self.visible? ? '' : ' (Hidden)'
"#{display_name}#{hidden_text}"
end
def initialize(properties = {})
self.visible = true if properties['visible'].nil?
self.highlight_information = HighlightInformation.new
self.editable = true if properties['editable'].nil?
self.matchable = false if properties ['matchable'].nil?
self.attributes = properties
create_unique_id
end
def attributes=(properties)
super properties
if option_strings
@options = FieldOption.create_field_options(name, option_strings)
end
end
def option_strings=(value)
if value
value = value.gsub(/\r\n?/, "\n").split("\n") if value.is_a?(String)
self.option_strings_text = value.select { |x| !"#{x}".strip.empty? }.map(&:rstrip).join("\n")
end
end
def option_strings
return [] unless option_strings_text
return option_strings_text if option_strings_text.is_a?(Array)
option_strings_text.gsub(/\r\n?/, "\n").split("\n")
end
def tag_id(model)
"#{model.class.name.downcase}_#{name}"
end
def tag_name_attribute(model)
"#{model.class.name.downcase}[#{name}]"
end
def select_options
select_options = []
select_options << ['(Select...)', '']
select_options + @options.map { |option| [option.option_name, option.option_name] }
end
def highlighted?
highlight_information[:highlighted]
end
def highlight_with_order(order)
highlight_information[:highlighted] = true
highlight_information[:order] = order
end
def unhighlight
self.highlight_information = HighlightInformation.new
end
def self.find_by_name(name)
Field.by_name(:key => name.downcase).first
end
def can_be_used_for_matching?
[TEXT_FIELD, TEXT_AREA, SELECT_BOX].include? type
end
def visible?
self[:visible] && (form.nil? || form.visible?)
end
private
def create_unique_id
self.name = UUIDTools::UUID.random_create.to_s.split('-').first if name.nil?
end
def validate_has_2_options
return true unless type == RADIO_BUTTON || type == SELECT_BOX
return errors.add(:option_strings, I18n.t('errors.models.field.has_2_options')) if option_strings.nil? || option_strings.length < 2
true
end
def validate_has_a_option
return true unless (type == CHECK_BOXES)
return errors.add(:option_strings, I18n.t('errors.models.field.has_1_option')) if option_strings.nil? || option_strings.length < 1
true
end
def validate_unique_name
return unless form
return errors.add(:name, I18n.t('errors.models.field.unique_name_this')) if form.fields.any? { |field| !field.equal?(self) && field.name == name }
other_form = FormSection.get_form_containing_field name
return errors.add(:name, I18n.t('errors.models.field.unique_name_other', :form_name => other_form.name)) if !other_form.nil? && form.id != other_form.id
true
end
end