From bdec83b3b6d4588fd46de557a5d483ff32fdc456 Mon Sep 17 00:00:00 2001 From: Mark Moser Date: Mon, 22 Aug 2016 11:49:02 -0500 Subject: [PATCH] validates input_options based on input type --- app/models/question.rb | 17 +++++-- .../input_options_presence_validator.rb | 11 +++++ test/models/question_test.rb | 13 +++-- .../test_helpers/input_options_validatable.rb | 6 +++ .../input_options_presence_validator_test.rb | 49 +++++++++++++++++++ 5 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 app/validators/input_options_presence_validator.rb create mode 100644 test/test_helpers/input_options_validatable.rb create mode 100644 test/validators/input_options_presence_validator_test.rb diff --git a/app/models/question.rb b/app/models/question.rb index 9258649..cdcdb3e 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -4,8 +4,17 @@ class Question < ApplicationRecord has_many :answers belongs_to :quiz - validates_presence_of :quiz_id - validates_presence_of :question - validates_presence_of :category - validates_presence_of :input_type + before_validation :compact_input_options + + validates :quiz_id, presence: true + validates :question, presence: true + validates :category, presence: true + validates :input_type, presence: true + validates :input_options, input_options_presence: true + + private + + def compact_input_options + self.input_options = input_options.reject(&:blank?) + end end diff --git a/app/validators/input_options_presence_validator.rb b/app/validators/input_options_presence_validator.rb new file mode 100644 index 0000000..0bb6284 --- /dev/null +++ b/app/validators/input_options_presence_validator.rb @@ -0,0 +1,11 @@ +class InputOptionsPresenceValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + return true unless record.input_type =~ /radio|check/i + return true if value.present? && value.count > 0 + + record.errors[attribute] << (options[:message] || + "You must provide answer options for the selected input type.") + + false + end +end diff --git a/test/models/question_test.rb b/test/models/question_test.rb index 88f6ea7..c5465fa 100644 --- a/test/models/question_test.rb +++ b/test/models/question_test.rb @@ -1,7 +1,14 @@ require 'test_helper' class QuestionTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end + test 'should compact arrays for input_options' do + question = Question.new(quiz_id: quizzes(:fed).to_i, + question: 'foo', + category: 'bar', + input_type: 'radio', + input_options: ['one', 'two', '', ' ', nil]) + question.validate + + assert_equal 2, question.input_options.count + end end diff --git a/test/test_helpers/input_options_validatable.rb b/test/test_helpers/input_options_validatable.rb new file mode 100644 index 0000000..85c26aa --- /dev/null +++ b/test/test_helpers/input_options_validatable.rb @@ -0,0 +1,6 @@ +class InputOptionsValidatable + include ActiveModel::Validations + attr_accessor :input_type + attr_accessor :input_options + validates :input_options, input_options_presence: true +end diff --git a/test/validators/input_options_presence_validator_test.rb b/test/validators/input_options_presence_validator_test.rb new file mode 100644 index 0000000..b827af2 --- /dev/null +++ b/test/validators/input_options_presence_validator_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' + +class InputOptionsPresenceValidatorTest < ActiveSupport::TestCase + test "should pass when inpute type not radio or checkbox" do + obj = InputOptionsValidatable.new + obj.input_type = "text" + + assert obj.valid? + assert_equal 0, obj.errors.messages[:input_options].count + end + + test "should fail when missing options for radio" do + obj = InputOptionsValidatable.new + obj.input_type = "radio" + obj.input_options = nil + obj.valid? + + refute obj.errors.messages.empty?, 'needs an error message' + assert_match(/provide.*option/i, obj.errors.messages[:input_options].join) + end + + test "should pass when provided options for radio" do + obj = InputOptionsValidatable.new + obj.input_type = "radio" + obj.input_options = ['one', 'two', nil] + + assert obj.valid? + assert_equal 0, obj.errors.messages[:input_options].count + end + + test "should fail when missing options for checkbox" do + obj = InputOptionsValidatable.new + obj.input_type = "checkbox" + obj.input_options = nil + obj.valid? + + refute obj.errors.messages.empty?, 'needs an error message' + assert_match(/provide.*option/i, obj.errors.messages[:input_options].join) + end + + test "should pass when provided options for checkbox" do + obj = InputOptionsValidatable.new + obj.input_type = "checkbox" + obj.input_options = ['one', 'two', nil] + + assert obj.valid? + assert_equal 0, obj.errors.messages[:input_options].count + end +end