class Attributor::HashDSLCompiler::Requirement

A class that encapsulates the definition of a requirement for Hash attributes It implements the validation against incoming values and it describes its format for documentation purposes

Attributes

attr_names[R]
description[R]
number[R]
type[R]

Public Class Methods

new(description: nil, **spec) click to toggle source
# File lib/attributor/hash_dsl_compiler.rb, line 13
def initialize(description: nil, **spec)
  @description = description
  @type = spec.keys.first
  case type
  when :all
    of(*spec[type])
  when :exclusive
    of(*spec[type])
  else
    @number = spec[type]
  end
end

Public Instance Methods

describe(_shallow = false, _example: nil) click to toggle source
# File lib/attributor/hash_dsl_compiler.rb, line 68
def describe(_shallow = false, _example: nil)
  hash = { type: type, attributes: attr_names }
  hash[:count] = number unless number.nil?
  hash[:description] = description unless description.nil?
  hash
end
of(*args) click to toggle source
# File lib/attributor/hash_dsl_compiler.rb, line 26
def of(*args)
  @attr_names = args
  self
end
validate(keys, context = Attributor::DEFAULT_ROOT_CONTEXT, _attribute = nil) click to toggle source
# File lib/attributor/hash_dsl_compiler.rb, line 31
def validate(keys, context = Attributor::DEFAULT_ROOT_CONTEXT, _attribute = nil)
  result = []
  case type
  when :all
    rest = attr_names - keys
    unless rest.empty?
      rest.each do |attr|
        sub_context = Attributor::Hash.generate_subcontext(context, attr)
        result.push "Attribute #{Attributor.humanize_context(sub_context)} is required."
      end
    end
  when :exactly
    included = attr_names & keys
    unless included.size ==  number
      result.push "Exactly #{number} of the following attributes #{attr_names} are required for #{Attributor.humanize_context(context)}. Found #{included.size} instead: #{included.inspect}"
    end
  when :at_most
    rest = attr_names & keys
    if rest.size > number
      found = rest.empty? ? 'none' : rest.inspect
      result.push "At most #{number} attributes out of #{attr_names} can be passed in for #{Attributor.humanize_context(context)}. Found #{found}"
    end
  when :at_least
    rest = attr_names & keys
    if rest.size < number
      found = rest.empty? ? 'none' : rest.inspect
      result.push "At least #{number} attributes out of #{attr_names} are required to be passed in for #{Attributor.humanize_context(context)}. Found #{found}"
    end
  when :exclusive
    intersection = attr_names & keys
    if intersection.size > 1
      result.push "Attributes #{intersection.inspect} are mutually exclusive for #{Attributor.humanize_context(context)}."
    end
  end
  result
end