From a0d7ed2078518cf03d56a4cd2c66b2bcdb9d653f Mon Sep 17 00:00:00 2001 From: Sam Davies Date: Wed, 10 Jan 2024 15:41:30 +0700 Subject: [PATCH] WEB-6757: Improving lesson and segment validation --- app/models/lesson.rb | 1 + app/models/lessons_validator.rb | 20 +++++++--------- app/models/segments_validator.rb | 39 ++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 12 deletions(-) create mode 100644 app/models/segments_validator.rb diff --git a/app/models/lesson.rb b/app/models/lesson.rb index 7f5499d..ce70093 100644 --- a/app/models/lesson.rb +++ b/app/models/lesson.rb @@ -12,6 +12,7 @@ class Lesson attr_markdown :description, source: :description_md, file: false attr_markdown :learning_objectives, source: :learning_objectives_md, file: false validates :title, :ordinal, :ref, presence: true + validates :segments, length: { minimum: 1 }, allow_blank: false, segments: true def initialize(attributes = {}) super diff --git a/app/models/lessons_validator.rb b/app/models/lessons_validator.rb index aca3586..cbeb196 100644 --- a/app/models/lessons_validator.rb +++ b/app/models/lessons_validator.rb @@ -19,24 +19,20 @@ def check_correct_class(record, attribute, value) def check_unique_refs(record, attribute, value) return unless value.is_a?(Array) - value.each do |lesson| - ref_counts = Hash.new(0) - lesson.segments.each { |segment| ref_counts[segment.ref] += 1 } - non_unique_refs = ref_counts.select { |_, count| count > 1 }.keys + ref_counts = Hash.new(0) + value.each { |lesson| ref_counts[lesson.ref] += 1 } + non_unique_refs = ref_counts.select { |_, count| count > 1 }.keys - non_unique_refs.each { |ref| record.errors.add(attribute, "(#{lesson.title}) segment ref #{ref} is not unique") } - end + non_unique_refs.each { |ref| record.errors.add(attribute, "=> ref '#{ref}' is not unique") } end def check_unique_title(record, attribute, value) return unless value.is_a?(Array) - value.each do |lesson| - title_counts = Hash.new(0) - lesson.segments.each { |segment| title_counts[segment.title] += 1 } - non_unique_titles = title_counts.select { |_, count| count > 1 }.keys + title_counts = Hash.new(0) + value.each { |lesson| title_counts[lesson.title] += 1 } + non_unique_titles = title_counts.select { |_, count| count > 1 }.keys - non_unique_titles.each { |title| record.errors.add(attribute, "(#{lesson.title}) segment title #{title} is not unique") } - end + non_unique_titles.each { |title| record.errors.add(attribute, "=> Title '#{title}' is not unique") } end end diff --git a/app/models/segments_validator.rb b/app/models/segments_validator.rb new file mode 100644 index 0000000..02fabfc --- /dev/null +++ b/app/models/segments_validator.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +# A validator that will check an array of choices for uniqueness of ref +class SegmentsValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + return unless value.is_a?(Array) + + check_correct_class(record, attribute, value) + check_unique_refs(record, attribute, value) + check_unique_title(record, attribute, value) + end + + def check_correct_class(record, attribute, value) + value.each do |segment| + record.errors.add(attribute, "segment #{segment} needs to be a quiz, video or text") unless [Assessment::Quiz, Video, Text].any? { |klass| segment.is_a?(klass) } + end + end + + def check_unique_refs(record, attribute, value) + return unless value.is_a?(Array) + + ref_counts = Hash.new(0) + value.each { |segment| ref_counts[segment.ref] += 1 } + non_unique_refs = ref_counts.select { |_, count| count > 1 }.keys + + non_unique_refs.each { |ref| record.errors.add(attribute, "(#{record.title}) => Segment ref '#{ref}' is not unique") } + end + + def check_unique_title(record, attribute, value) + return unless value.is_a?(Array) + + title_counts = Hash.new(0) + + value.each { |segment| title_counts[segment.title] += 1 } + non_unique_titles = title_counts.select { |_, count| count > 1 }.keys + + non_unique_titles.each { |title| record.errors.add(attribute, "(#{record.title}) => Segment title '#{title}' is not unique") } + end +end