Class: CMDx::Coercions

Inherits:
Object
  • Object
show all
Defined in:
lib/cmdx/coercions.rb,
lib/cmdx/coercions/date.rb,
lib/cmdx/coercions/hash.rb,
lib/cmdx/coercions/time.rb,
lib/cmdx/coercions/array.rb,
lib/cmdx/coercions/float.rb,
lib/cmdx/coercions/coerce.rb,
lib/cmdx/coercions/string.rb,
lib/cmdx/coercions/symbol.rb,
lib/cmdx/coercions/boolean.rb,
lib/cmdx/coercions/complex.rb,
lib/cmdx/coercions/integer.rb,
lib/cmdx/coercions/rational.rb,
lib/cmdx/coercions/date_time.rb,
lib/cmdx/coercions/big_decimal.rb

Overview

Registry of named type coercions applied to input/output values. Ships with built-ins for ‘:array`, `:big_decimal`, `:boolean`, `:complex`, `:date`, `:date_time`, `:float`, `:hash`, `:integer`, `:rational`, `:string`, `:symbol`, `:time`. Coercion handlers return the coerced value on success, or a Failure carrying an i18n message on failure.

Defined Under Namespace

Modules: Array, BigDecimal, Boolean, Coerce, Complex, Date, DateTime, Float, Hash, Integer, Rational, String, Symbol, Time Classes: Failure

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCoercions

Returns a new instance of Coercions.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/cmdx/coercions.rb', line 17

def initialize
  @registry = {
    array: Coercions::Array,
    big_decimal: Coercions::BigDecimal,
    boolean: Coercions::Boolean,
    complex: Coercions::Complex,
    date: Coercions::Date,
    date_time: Coercions::DateTime,
    float: Coercions::Float,
    hash: Coercions::Hash,
    integer: Coercions::Integer,
    rational: Coercions::Rational,
    string: Coercions::String,
    symbol: Coercions::Symbol,
    time: Coercions::Time
  }
end

Instance Attribute Details

#registryObject (readonly)

Returns the value of attribute registry.



15
16
17
# File 'lib/cmdx/coercions.rb', line 15

def registry
  @registry
end

Instance Method Details

#coerce(task, name, value, rules) ⇒ Object, Failure

Applies each coercion rule to ‘value`. Returns the first successful coercion. When every rule fails and more than one was declared (and none were inline callables), the aggregated “into_any” message is recorded; otherwise the last individual failure is used.

Parameters:

  • task (Task)

    used for inline ‘Symbol`/`Proc` handlers and error recording

  • name (Symbol)

    attribute name for error reporting

  • value (Object)

    raw input before coercion rules run

  • rules (Array<Array(Object, Hash)>)

    from #extract

Returns:

  • (Object, Failure)

    coerced value, or ‘Failure` when every rule failed



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/cmdx/coercions.rb', line 143

def coerce(task, name, value, rules)
  return value if rules.empty?

  last_failure = nil
  any_inline = false

  rules.each do |handler, opts|
    result =
      if handler.is_a?(::Symbol) && registry.key?(handler)
        lookup(handler).call(value, **opts)
      else
        any_inline = true
        Coercions::Coerce.call(task, value, handler)
      end

    return result unless result.is_a?(Failure)

    last_failure = result
  end

  if rules.size > 1 && !any_inline
    type_names   = rules.map { |h, _| I18nProxy.t("cmdx.types.#{h}") }.join(", ")
    last_failure = Failure.new(I18nProxy.t("cmdx.coercions.into_any", types: type_names))
  end

  task.errors.add(name, last_failure.message)
  last_failure
end

#deregister(name) ⇒ Coercions

Returns self for chaining.

Parameters:

Returns:



69
70
71
72
# File 'lib/cmdx/coercions.rb', line 69

def deregister(name)
  registry.delete(name)
  self
end

#empty?Boolean

Returns:



124
125
126
# File 'lib/cmdx/coercions.rb', line 124

def empty?
  registry.empty?
end

#extract(options) ⇒ Array<Array(Object, Hash)>

Normalizes the ‘:coerce` declaration on an input/output into a list of `[handler, opts]` pairs. Accepts a Symbol, Array, Hash, or any callable.

Parameters:

  • options (Hash{Symbol => Object})

    declaration options

Options Hash (options):

  • :coerce (Object)

    coercion rule(s): Symbol, Array, Hash, or ‘#call`-able

Returns:

  • (Array<Array(Object, Hash)>)

    pairs of handler + per-handler options

Raises:

  • (ArgumentError)

    when ‘:coerce` is an unsupported format



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/cmdx/coercions.rb', line 100

def extract(options)
  return EMPTY_ARRAY if options.empty?

  raw = options[:coerce]
  return EMPTY_ARRAY if raw.nil? || raw == EMPTY_ARRAY

  case raw
  when ::Symbol
    [[raw, EMPTY_HASH]]
  when ::Array
    raw.map { |t| normalize_entry(t) }
  when ::Hash
    raw.map { |k, v| [k, v == true ? EMPTY_HASH : v] }
  else
    return [[raw, EMPTY_HASH]] if raw.respond_to?(:call)

    raise ArgumentError, <<~MSG.chomp
      unsupported :coerce format #{raw.inspect}; expected Symbol, Array, Hash, or a callable.
      See https://drexed.github.io/cmdx/inputs/coercions/#declarations
    MSG
  end
end

#initialize_copy(source) ⇒ void

This method returns an undefined value.

Parameters:

  • source (Coercions)

    registry to duplicate



37
38
39
# File 'lib/cmdx/coercions.rb', line 37

def initialize_copy(source)
  @registry = source.registry.dup
end

#key?(name) ⇒ Boolean

Returns whether a coercion is registered under ‘name`.

Parameters:

Returns:

  • (Boolean)

    whether a coercion is registered under ‘name`



76
77
78
# File 'lib/cmdx/coercions.rb', line 76

def key?(name)
  registry.key?(name)
end

#lookup(name) ⇒ #call

Returns the registered coercion.

Parameters:

Returns:

  • (#call)

    the registered coercion

Raises:



83
84
85
86
87
88
89
90
# File 'lib/cmdx/coercions.rb', line 83

def lookup(name)
  registry[name] || begin
    raise UnknownEntryError, <<~MSG.chomp
      unknown coercion #{name.inspect}; registered: #{registry.keys.inspect}.
      See https://drexed.github.io/cmdx/inputs/coercions/#built-in-coercions
    MSG
  end
end

#register(name, callable = nil, &block) {|see built-in coercion signatures — `call(value, options = {})`| ... } ⇒ Coercions

Registers a named coercion, overwriting any existing entry with the same name.

Parameters:

  • name (Symbol)
  • callable (#call, nil) (defaults to: nil)

    pass either this or a block

  • block (#call, nil)

    coercion implementation when ‘callable` is omitted

Yields:

  • (see built-in coercion signatures — `call(value, options = {})`)

Returns:

Raises:

  • (ArgumentError)

    when both ‘callable` and a block are given, or when the resolved coercion isn’t callable



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/cmdx/coercions.rb', line 51

def register(name, callable = nil, &block)
  coercion = callable || block

  if callable && block
    raise ArgumentError, "coercion: provide either a callable or a block, not both"
  elsif !coercion.respond_to?(:call)
    raise ArgumentError, <<~MSG.chomp
      coercion must respond to #call (got #{coercion.class}).
      See https://drexed.github.io/cmdx/inputs/coercions/#declarations
    MSG
  end

  registry[name.to_sym] = coercion
  self
end

#sizeInteger

Returns:



129
130
131
# File 'lib/cmdx/coercions.rb', line 129

def size
  registry.size
end