lib/dsu/validators/entries_validator.rb in dsu-0.1.0.alpha.5 vs lib/dsu/validators/entries_validator.rb in dsu-1.0.0

- old
+ new

@@ -5,58 +5,69 @@ # https://guides.rubyonrails.org/active_record_validations.html#validates-with module Dsu module Validators class EntriesValidator < ActiveModel::Validator - include Dsu::Support::FieldErrors + include Support::FieldErrors def validate(record) - raise 'options[:fields] is not defined.' unless options.key? :fields - raise 'options[:fields] is not an Array.' unless options[:fields].is_a? Array - raise 'options[:fields] elements are not Symbols.' unless options[:fields].all?(Symbol) + unless record.entries.is_a?(Array) + record.errors.add(:entries_entry, 'is the wrong object type. ' \ + "\"Array\" was expected, but \"#{record.entries.class}\" was received.") + end - options[:fields].each do |field| - entries = record.send(field) + validate_entry_types record + validate_unique_entry record + validate_entries record + end - unless entries.is_a?(Array) - record.errors.add(field, 'is the wrong object type. ' \ - "\"Array\" was expected, but \"#{entries.class}\" was received.") - next - end + private - validate_entry_types field, entries, record - validate_unique_entry_attr :uuid, field, entries, record - validate_unique_entry_attr :description, field, entries, record + def validate_entry_types(record) + record.entries.each do |entry| + next if entry.is_a? Dsu::Models::Entry + + record.errors.add(:entries_entry, 'entry Array element is the wrong object type. ' \ + "\"Entry\" was expected, but \"#{entry.class}\" was received.", + type: Support::FieldErrors::FIELD_TYPE_ERROR) end end - private + def validate_unique_entry(record) + return unless record.entries.is_a? Array - def validate_entry_types(field, entries, record) - entries.each do |entry| - next if entry.is_a? Dsu::Models::Entry + entry_objects = record.entries.select { |entry| entry.is_a?(Dsu::Models::Entry) } - record.errors.add(field, 'entry Array element is the wrong object type. ' \ - "\"Entry\" was expected, but \"#{entry.class}\" was received.", - type: Dsu::Support::FieldErrors::FIELD_TYPE_ERROR) + descriptions = entry_objects.map(&:description) + return if descriptions.uniq.length == descriptions.length - next + non_unique_descriptions = descriptions.select { |description| descriptions.count(description) > 1 }.uniq + if non_unique_descriptions.any? + record.errors.add(:entries_entry, 'contains a duplicate entry: ' \ + "#{format_non_unique_descriptions(non_unique_descriptions)}.", + type: Support::FieldErrors::FIELD_DUPLICATE_ERROR) end end - def validate_unique_entry_attr(attr, field, entries, record) - return unless entries.is_a? Array + def validate_entries(record) + entries = record.entries + return if entries.none? - entry_objects = entries.select { |entry| entry.is_a?(Dsu::Models::Entry) } + entries.each do |entry| + next if entry.valid? - attrs = entry_objects.map(&attr) - return if attrs.uniq.length == attrs.length - - non_unique_attrs = attrs.select { |attr| attrs.count(attr) > 1 }.uniq # rubocop:disable Lint/ShadowingOuterLocalVariable - if non_unique_attrs.any? - record.errors.add(field, "contains duplicate ##{attr}s: #{non_unique_attrs.join(', ')}.", - type: Dsu::Support::FieldErrors::FIELD_DUPLICATE_ERROR) + entry.errors.each do |error| + record.errors.add(:entries_entry, error.full_message) + end end + end + + def format_non_unique_descriptions(non_unique_descriptions) + non_unique_descriptions.map { |description| "\"#{short_description(description)}\"" }.join(', ') + end + + def short_description(description) + Models::Entry.short_description(string: description) end end end end