Sha256: 788e28986e065afc68376260ae3bbda03cc678f0ae00c6cf229d60bc6aa9f723

Contents?: true

Size: 1.6 KB

Versions: 1

Compression:

Stored size: 1.6 KB

Contents

# frozen_string_literal: true

require 're_sorcery/fielded/expand_internal_fields'

module ReSorcery
  module Fielded
    include Helpers

    module ClassMethods
      include Decoder::BuiltinDecoders

      private

      # Set a field for instances of a class
      #
      # There is intentionally no way to make fields optionally nil. Use a type
      # that more meaningfully represents an empty value instead, such as a
      # `Maybe` type or discriminated unions.
      #
      # @param [Symbol] name
      # @param [arg of Decoder.is] type @see `ReSorcery::Decoder.is` for details
      # @param [Proc] pro: in the context of an instance of the class, return the value of the field
      def field(name, type, pro = -> { send(name) })
        ArgCheck['name', name, Symbol]
        ArgCheck['pro', pro, Proc]

        (@fields ||= {})[name] = { type: is(type), pro: pro }
      end
    end

    def self.included(base)
      base.extend(ClassMethods)
    end

    # Returns the `Decoder#test`ed fields of the object, wrapped in a `Result`
    #
    # If all the `Decoder`s pass, this will return an `Ok`. If any of them
    # fail, it will return an `Err` instead.
    #
    # @return [Result<String, Hash>]
    def fields
      self.class.instance_exec { @fields ||= [] }.inject(ok({})) do |result_hash, (name, field_hash)|
        result_hash.assign(name) do
          field_hash[:type].test(instance_exec(&field_hash[:pro]))
            .and_then { |tested| ExpandInternalFields.expand(tested) }
            .map_error { |error| "Error at field `#{name}` of `#{self.class}`: #{error}" }
        end
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
re_sorcery-0.2.0 lib/re_sorcery/fielded.rb