Class: MetadataPresenter::BaseValidator Abstract

Inherits:
Object
  • Object
show all
Defined in:
app/validators/metadata_presenter/base_validator.rb

Overview

This class is abstract.

Abstract base class for validation utilities. Provides an interface for implementing validation from the metadata.

The Base validator expects the subclass to implement only #invalid_answer? as long the conventions are followed:

  1. The default metadata for error messages follows the “error.name_of_the_class_without_validator”

  2. The class should have the same name as the schema e.g ‘required’ will lookup for RequiredValidator.

On the example below the base validator will look for the custom message on “errors” -> “grogu” -> “any” and if there is none, then will look for the default message on default metadata as “error.grogu”.

Examples:

Custom validator

class GroguValidator < BaseValidator
  def invalid_answer?
    user_answer = answers[component.name]

    user_answer.to_s == 'Grogu'
  end
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(page_answers:, component:) ⇒ BaseValidator



35
36
37
38
# File 'app/validators/metadata_presenter/base_validator.rb', line 35

def initialize(page_answers:, component:)
  @page_answers = page_answers
  @component = component
end

Instance Attribute Details

#componentMetadataPresenter::Component (readonly)



33
34
35
# File 'app/validators/metadata_presenter/base_validator.rb', line 33

def component
  @component
end

#page_answersMetadataPresenter::PageAnswers (readonly)



30
31
32
# File 'app/validators/metadata_presenter/base_validator.rb', line 30

def page_answers
  @page_answers
end

Instance Method Details

#allow_blank?TrueClass

Method signature to be overwrite in the subclass if you do not want to allow blank values. We should not allow blank when performing the required validation.



129
130
131
# File 'app/validators/metadata_presenter/base_validator.rb', line 129

def allow_blank?
  user_answer.blank? && !self.class.name.demodulize.include?('RequiredValidator')
end

#custom_error_messageString

The custom message will be lookup from the schema key on the metadata. Assuming for example that the schema key is ‘grogu’ then the message will lookup for ‘errors.grogu.any’.



57
58
59
60
61
# File 'app/validators/metadata_presenter/base_validator.rb', line 57

def custom_error_message
  message = component.dig('errors', schema_key, 'any')

  message % error_message_hash if message.present?
end

#default_error_messageString

The default error message will be look using the schema key. Assuming the schema key is ‘grogu’ then the default message will look for ‘error.grogu.value’.

is not present

Raises:



76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'app/validators/metadata_presenter/base_validator.rb', line 76

def default_error_message
  default_error_message_key = "error.#{schema_key}"
  default_message = Rails
                      .application
                      .config
                      .[default_error_message_key]

  if default_message.present?
    default_message['value'] % error_message_hash
  else
    raise NoDefaultMessage, "No default message found for key '#{default_error_message_key}'."
  end
end

#error_message_hashObject

Error message hash that will be interpolate with the custom message or the default metadata

The message could include ‘%control’ to add the label name. Or for the GroguValidator will be ‘%grogu’ and the value setup in the metadata.



116
117
118
119
120
121
# File 'app/validators/metadata_presenter/base_validator.rb', line 116

def error_message_hash
  {
    control: component.humanised_title,
    schema_key.to_sym => component.validation[schema_key]
  }
end

#invalid_answer?TrueClass, FalseClass

Needs to be implemented on the subclass

Raises:

  • (NotImplementedError)


95
96
97
# File 'app/validators/metadata_presenter/base_validator.rb', line 95

def invalid_answer?
  raise NotImplementedError
end

#schema_keyString

The convention to be looked on the metadata is by the name of the class. E.g the GroguValidator will look for ‘grogu’ on the metadata. Overwrite this method if the validator doesn’t follow the convetions.

default metadata



106
107
108
# File 'app/validators/metadata_presenter/base_validator.rb', line 106

def schema_key
  @schema_key ||= self.class.name.demodulize.gsub('Validator', '').underscore
end

#user_answerString



65
66
67
# File 'app/validators/metadata_presenter/base_validator.rb', line 65

def user_answer
  page_answers.send(component.name)
end

#valid?Boolean



40
41
42
43
44
45
46
47
48
49
# File 'app/validators/metadata_presenter/base_validator.rb', line 40

def valid?
  return true if allow_blank?

  if invalid_answer?
    error_message = custom_error_message || default_error_message
    page_answers.errors.add(component.id, error_message)
  end

  page_answers.errors.blank?
end