Module: Coercive

Defined in:
lib/coercive.rb

Overview

Public: The Coercive module implements a succinct DSL for declaring callable modules that will validate and coerce input data to an expected format.

Defined Under Namespace

Classes: Error

Instance Method Summary collapse

Instance Method Details

#call(input) ⇒ Object

Public: Coercive the given input using the declared attribute coercions.

input - input Hash with string keys that correspond to declared attributes.

Returns a Hash with known attributes as string keys and coerced values. Raises a Coercive::Error if the given input is not a Hash, or if there are any unknown string keys in the Hash, or if the values for the known keys do not pass the inner coercions for the associated declared attributes.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/coercive.rb', line 25

def call(input)
  fail Coercive::Error.new("not_valid") unless input.is_a?(Hash)

  errors  = {}

  # Fetch attributes from the input Hash into the fetched_attrs Hash.
  #
  # Each fetch function is responsible for fetching its associated attribute
  # into the fetched_attrs Hash, or choosing not to fetch it, or choosing to
  # raise a Coercive::Error.
  #
  # These fetch functions encapsulate the respective strategies for dealing
  # with required, optional, or implicit attributes appropriately.
  fetched_attrs = {}
  attr_fetch_fns.each do |name, fetch_fn|
    begin
      fetch_fn.call(input, fetched_attrs)
    rescue Coercive::Error => e
      errors[name] = e.errors
    end
  end

  # Check for unknown names in the input (not declared, and thus not fetched).
  input.each_key do |name|
    errors[name] = "unknown" unless fetched_attrs.key?(name)
  end

  # Coercive fetched attributes into the coerced_attrs Hash.
  #
  # Each coerce function will coerce the given input value for that attribute
  # to an acceptable output value, or choose to raise a Coercive::Error.
  coerced_attrs = {}
  fetched_attrs.each do |name, value|
    coerce_fn = attr_coerce_fns.fetch(name)
    begin
      coerced_attrs[name] = coerce_fn.call(value)
    rescue Coercive::Error => e
      errors[name] = e.errors
    end
  end

  # Fail if fetching or coercion caused any errors.
  fail Coercive::Error.new(errors) unless errors.empty?

  coerced_attrs
end