Sha256: 8f82fb1c7437cb868efab244555befc2982b1d29fcb218c99035f416f88767f4

Contents?: true

Size: 1.92 KB

Versions: 1

Compression:

Stored size: 1.92 KB

Contents

require_relative "errors"
require_relative "convert"

module SmartKv::Meat
  # The meat of the gem

  include SmartKv::Convert

  def required(*args)
    init_required
    @required += args
    @optional -= @required if @optional
    @required
  end

  def required_keys
    init_required
    @required.to_a
  end

  def init_required
    @required ||= superclass == SmartKv ? Set.new : superclass.required.dup
  end

  def optional(*args)
    init_optional
    @optional += args
    @required -= @optional if @required
    @optional
  end

  def optional_keys
    init_optional
    @optional.to_a
  end

  def init_optional
    @optional ||= superclass == SmartKv ? Set.new : superclass.optional.dup
  end

  def keys
    Array(@required) + Array(@optional)
  end

  def check(kv={})
    prevent_direct_instantiation

    object_class = callable_class || kv.class
    kv = kv.dup

    unless SmartKv::Check.production?
      required_keys = Array(@required)
      optional_keys = Array(@optional)

      hash = kv.to_h
      missing_keys = required_keys - hash.keys
      unless missing_keys.empty?
        raise SmartKv::KeyError, "missing required key(s): #{missing_keys.map{|k| k.to_sym.inspect }.join(', ')} in #{self.class}"
      end

      unrecognized_keys = hash.keys - required_keys - optional_keys
      unless unrecognized_keys.empty?
        key = unrecognized_keys.first
        raise SmartKv::KeyError.new("unrecognized key: #{key.inspect} for #{self}.", key: key, receiver: (keys - hash.keys).map {|k| [k, nil] }.to_h)
      end
    end

    return to_callable_object(object_class, kv)
  end
  alias_method :new, :check

  def callable_as(klass)
    @callable_as = superclass == SmartKv ? klass : superclass.callable_class
  end

  def callable_class
    @callable_as
  end

private

  def prevent_direct_instantiation
    if self == SmartKv
      raise SmartKv::CheckError, "only subclass of SmartKv is meant to be used".freeze
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
smart_kv-0.2.7 lib/smart_kv/meat.rb