tomdalling/rschema

View on GitHub
lib/rschema/schemas/coercer.rb

Summary

Maintainability
A
0 mins
Test Coverage
# frozen_string_literal: true

module RSchema
  module Schemas
    #
    # A schema that applies a coercer to a value, before passing the coerced
    # value to a subschema.
    #
    # This is not a type of schema that you would typically create yourself.
    # It is used internally to implement RSchema's coercion functionality.
    #
    class Coercer
      attr_reader :coercer, :subschema

      def initialize(coercer, subschema)
        @coercer = coercer
        @subschema = subschema
      end

      def call(value, options)
        unless coercer.will_affect?(value)
          # short-circuit the coercer
          return @subschema.call(value, options)
        end

        result = coercer.call(value)
        if result.valid?
          @subschema.call(result.value, options)
        else
          failure(value, result.error)
        end
      end

      def with_wrapped_subschemas(wrapper)
        self.class.new(coercer, wrapper.wrap(subschema))
      end

      private

      def failure(value, name)
        Result.failure(
          Error.new(
            schema: self,
            value: value,
            symbolic_name: name || :coercion_failure,
          ),
        )
      end
    end
  end
end