lib/quby/compiler/services/definition_validator.rb in quby-compiler-0.5.7 vs lib/quby/compiler/services/definition_validator.rb in quby-compiler-0.5.8

- old
+ new

@@ -19,10 +19,11 @@ validate_fields(questionnaire) validate_questions(questionnaire) validate_scores(questionnaire) validate_table_edgecases(questionnaire) validate_flags(questionnaire) + validate_key_uniqueness(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) @@ -125,16 +126,23 @@ end end def validate_flags(questionnaire) questionnaire.flags.each_value do |flag| + ensure_valid_descriptions(questionnaire, flag) validate_flag_shows(questionnaire, flag) validate_flag_hides(questionnaire, flag) validate_flag_depends_on(questionnaire, flag) end end + def ensure_valid_descriptions(questionnaire, flag) + unless (flag.description_false.present? && flag.description_true.present?) || flag.description.present? + fail ArgumentError, "Flag '#{flag.key}' Requires at least either both description_true and description_false or a description" + end + end + 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 '#{flag.key}' has unknown shows_questions keys #{unknown_questions}" @@ -151,10 +159,22 @@ return if (missing = flag.depends_on - questionnaire.flags.keys).blank? fail ArgumentError, "Flag #{flag.key} depends_on nonexistent flag '#{missing.to_sentence}'" end + def validate_key_uniqueness(questionnaire) + keys = questionnaire.fields.answer_keys.to_a \ + + questionnaire.score_schemas.keys.map(&:to_sym) \ + + questionnaire.flags.keys.map { delete_prefix(_1, questionnaire).to_sym } \ + + questionnaire.textvars.keys.map { delete_prefix(_1, questionnaire).to_sym } + + return if keys.size == keys.uniq.size + + duplicates = keys.tally.filter_map { |k,v| k if v > 1 } + fail ArgumentError, "Duplicate keys: #{duplicates.to_sentence}" + end + def validate_respondent_types(questionnaire) valid_respondent_types = Entities::Questionnaire::RESPONDENT_TYPES invalid_types = questionnaire.respondent_types - valid_respondent_types @@ -336,9 +356,13 @@ def validate_html(html, key = nil) fragment = Nokogiri::HTML5.fragment(html, max_errors: 3) return unless fragment.errors.present? fail "#{key || html} contains invalid html: #{fragment.errors.map(&:to_s).join(', ')}." + end + + def delete_prefix(key, questionnaire) + key.delete_prefix("#{questionnaire.key}_") end end end end end