class AnswerFormatValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) send(record.question.input_type, record, attribute, value) end private def text record, attribute, value clean_val = value.to_s.strip.delete("\r") return if clean_val.length.between?(1, 1000) if clean_val.blank? record.errors[attribute] << (options[:message] || "Please enter an answer.") end if clean_val.length > 1000 record.errors[attribute] << (options[:message] || "The character limit for this answer is 1000.") end end def radio record, attribute, value return unless value.to_s.strip.blank? record.errors[attribute] << (options[:message] || "Please select an answer.") end def checkbox record, attribute, value return unless value.nil? || Array(value).join.blank? record.errors[attribute] << (options[:message] || "Please select an answer.") end def live_code record, attribute, value seed = (Question.find_by(id: record.question_id) || Question.new).input_options return unless value.nil? || value.values.join.blank? || !match_seed?(value, seed) record.errors[attribute] << (options[:message] || live_code_error_message(value)) end def with_other record, attribute, value return if value.present? && with_other_check(value) record.errors[attribute] << (options[:message] || "Please select or provide an answer.") end alias radio_other with_other alias checkbox_other with_other ################################# def with_other_check value return false unless value.respond_to? :keys return false if Array(value[:options]).join.blank? return false if value[:options].include?('other') && value[:other].to_s.blank? true end def live_code_error_message value if value.present? && value.keys.count == 1 return "Please check that you will come back to complete the code example." end "You must write comments or code in one of the textareas to progress." end def match_seed? value, seed s_value = value.stringify_keys s_seed = seed.stringify_keys keys = s_value.merge(s_seed).keys.uniq matches = keys.inject([]) do |memo, k| memo << (s_value[k].to_s.strip == s_seed[k].to_s.strip) end matches.include? false end end