Class: Quby::Questionnaires::Services::DefinitionValidator
- Inherits:
-
ActiveModel::Validator
- Object
- ActiveModel::Validator
- Quby::Questionnaires::Services::DefinitionValidator
- Defined in:
- lib/quby/questionnaires/services/definition_validator.rb
Constant Summary collapse
- MAX_KEY_LENGTH =
19
- KEY_PREFIX =
'v_'
Instance Attribute Summary collapse
-
#definition ⇒ Object
readonly
Returns the value of attribute definition.
-
#questionnaire ⇒ Object
readonly
Returns the value of attribute questionnaire.
Instance Method Summary collapse
- #subquestions_cant_have_default_invisible(question) ⇒ Object
- #to_be_hidden_questions_exist_and_not_subquestion?(questionnaire, option, msg_base:) ⇒ Boolean
- #to_be_shown_questions_exist_and_not_subquestion?(questionnaire, option, msg_base:) ⇒ Boolean
- #validate(definition) ⇒ Object
- #validate_fields(questionnaire) ⇒ Object
- #validate_flag_depends_on(questionnaire, flag) ⇒ Object
- #validate_flag_hides(questionnaire, flag) ⇒ Object
- #validate_flag_shows(questionnaire, flag) ⇒ Object
- #validate_flags(questionnaire) ⇒ Object
- #validate_outcome_tables(questionnaire) ⇒ Object
- #validate_presence_of_titles(question) ⇒ Object
- #validate_question(question) ⇒ Object
- #validate_question_options(questionnaire, question) ⇒ Object
- #validate_questions(questionnaire) ⇒ Object
- #validate_respondent_types(questionnaire) ⇒ Object
- #validate_scores(questionnaire) ⇒ Object
- #validate_table_edgecases(questionnaire) ⇒ Object
- #validate_title(questionnaire) ⇒ Object
Instance Attribute Details
#definition ⇒ Object (readonly)
Returns the value of attribute definition.
13 14 15 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 13 def definition @definition end |
#questionnaire ⇒ Object (readonly)
Returns the value of attribute questionnaire.
14 15 16 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 14 def questionnaire @questionnaire end |
Instance Method Details
#subquestions_cant_have_default_invisible(question) ⇒ Object
170 171 172 173 174 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 170 def subquestions_cant_have_default_invisible(question) if question.subquestion? && question.default_invisible fail "Question #{question.key} is a subquestion with default_invisible." end end |
#to_be_hidden_questions_exist_and_not_subquestion?(questionnaire, option, msg_base:) ⇒ Boolean
152 153 154 155 156 157 158 159 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 152 def to_be_hidden_questions_exist_and_not_subquestion?(questionnaire, option, msg_base:) return if option.hides_questions.blank? msg_base += " hides_questions" option.hides_questions.each do |key| validate_question_key_exists?(questionnaire, key, msg_base: msg_base) validate_not_subquestion(questionnaire, key, msg_base: msg_base) end end |
#to_be_shown_questions_exist_and_not_subquestion?(questionnaire, option, msg_base:) ⇒ Boolean
161 162 163 164 165 166 167 168 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 161 def to_be_shown_questions_exist_and_not_subquestion?(questionnaire, option, msg_base:) return if option.shows_questions.blank? msg_base += " shows_questions" option.shows_questions.each do |key| validate_question_key_exists?(questionnaire, key, msg_base: msg_base) validate_not_subquestion(questionnaire, key, msg_base: msg_base) end end |
#validate(definition) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 16 def validate(definition) questionnaire = DSL.build_from_definition(definition) validate_fields(questionnaire) validate_title(questionnaire) validate_questions(questionnaire) validate_scores(questionnaire) validate_table_edgecases(questionnaire) validate_flags(questionnaire) validate_respondent_types(questionnaire) validate_outcome_tables(questionnaire) validate_markdown_fields(questionnaire) if questionnaire.validate_html validate_raw_content_items(questionnaire) if questionnaire.validate_html # Some compilation errors are Exceptions (pure syntax errors) and some StandardErrors (NameErrors) rescue Exception => exception # rubocop:disable Lint/RescueException definition.errors.add(:sourcecode, {message: "Questionnaire error: #{definition.key}\n" \ "#{exception.}", backtrace: exception.backtrace[0..5].join("<br/>")}) end |
#validate_fields(questionnaire) ⇒ Object
35 36 37 38 39 40 41 42 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 35 def validate_fields(questionnaire) questionnaire.fields.input_keys .find { |k| !k.is_a?(Symbol) } &.tap { |k| fail "Input key #{k} is not a symbol" } questionnaire.fields.answer_keys .find { |k| !k.is_a?(Symbol) } &.tap { |k| fail "Answer key #{k} is not a symbol" } end |
#validate_flag_depends_on(questionnaire, flag) ⇒ Object
128 129 130 131 132 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 128 def validate_flag_depends_on(questionnaire, flag) return if flag.depends_on.blank? || questionnaire.flags.key?(flag.depends_on) fail ArgumentError, "Flag #{flag.key} depends_on nonexistent flag '#{flag.depends_on}'" end |
#validate_flag_hides(questionnaire, flag) ⇒ Object
121 122 123 124 125 126 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 121 def validate_flag_hides(questionnaire, flag) unknown_questions = flag.hides_questions.select { |key| !questionnaire.key_in_use?(key) } return if unknown_questions.blank? fail ArgumentError, "Flag '#{key}' has unknown hides_questions keys #{unknown_questions}" end |
#validate_flag_shows(questionnaire, flag) ⇒ Object
114 115 116 117 118 119 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 114 def validate_flag_shows(questionnaire, flag) unknown_questions = flag.shows_questions.select { |key| !questionnaire.key_in_use?(key) } return if unknown_questions.blank? fail ArgumentError, "Flag '#{key}' has unknown shows_questions keys #{unknown_questions}" end |
#validate_flags(questionnaire) ⇒ Object
106 107 108 109 110 111 112 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 106 def validate_flags(questionnaire) questionnaire.flags.each_value do |flag| validate_flag_shows(questionnaire, flag) validate_flag_hides(questionnaire, flag) validate_flag_depends_on(questionnaire, flag) end end |
#validate_outcome_tables(questionnaire) ⇒ Object
145 146 147 148 149 150 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 145 def validate_outcome_tables(questionnaire) questionnaire.outcome_tables.each do |table| next if table.valid? fail "Outcome table #{table.errors.}" end end |
#validate_presence_of_titles(question) ⇒ Object
89 90 91 92 93 94 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 89 def validate_presence_of_titles(question) return if question.allow_blank_titles if !question.subquestion? && question.title.blank? && question.context_free_title.blank? fail "Question #{question.key} must define either `:title` or `:context_free_title`." end end |
#validate_question(question) ⇒ Object
68 69 70 71 72 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 68 def validate_question(question) unless question.valid? fail "Question #{question.key} is invalid: #{question.errors..join(', ')}" end end |
#validate_question_options(questionnaire, question) ⇒ Object
81 82 83 84 85 86 87 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 81 def (questionnaire, question) question..each do |option| msg_base = "Question #{option.question.key} option #{option.key}" to_be_hidden_questions_exist_and_not_subquestion?(questionnaire, option, msg_base: msg_base) to_be_shown_questions_exist_and_not_subquestion?(questionnaire, option, msg_base: msg_base) end end |
#validate_questions(questionnaire) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 50 def validate_questions(questionnaire) questionnaire.answer_keys.each do |key| validate_key_format(key) end questionnaire.question_hash.each_value do |question| validate_question(question) subquestions_cant_have_default_invisible question validate_subquestion_absence_in_select question question validate_values_unique question (questionnaire, question) validate_presence_of_titles question validate_no_spaces_before_question_nr_in_title question end end |
#validate_respondent_types(questionnaire) ⇒ Object
134 135 136 137 138 139 140 141 142 143 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 134 def validate_respondent_types(questionnaire) valid_respondent_types = Entities::Questionnaire::RESPONDENT_TYPES invalid_types = questionnaire.respondent_types - valid_respondent_types if invalid_types.present? fail "Invalid respondent types: :#{invalid_types.join(', :')}\n"\ "Choose one or more from: :#{valid_respondent_types.join(', :')}" end end |
#validate_scores(questionnaire) ⇒ Object
74 75 76 77 78 79 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 74 def validate_scores(questionnaire) questionnaire.scores.each do |score| validate_score_key_length(score) validate_score_label_present(score) end end |
#validate_table_edgecases(questionnaire) ⇒ Object
96 97 98 99 100 101 102 103 104 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 96 def validate_table_edgecases(questionnaire) questionnaire.panels.each do |panel| tables = panel.items.select { |item| item.is_a?(Entities::Table) } tables.each do |table| questions = table.items.select { |item| item.is_a?(Entities::Question) } questions.each { |question| validate_table_question(question) } end end end |
#validate_title(questionnaire) ⇒ Object
44 45 46 47 48 |
# File 'lib/quby/questionnaires/services/definition_validator.rb', line 44 def validate_title(questionnaire) if questionnaire.title.blank? fail "Questionnaire title is missing." end end |