Sha256: 29e530f392b4a5ab1087379a2e4f3d5947fb6a1b1e87b9ba7d1944cfbc1db8a3

Contents?: true

Size: 1.88 KB

Versions: 2

Compression:

Stored size: 1.88 KB

Contents

module Twfy

  class Validation

    class ServiceArgumentError < ::ArgumentError; end

    def self.run(params = {}, against = {})
      new(params, against).check!
    end

    def initialize(params = {}, against = {})
      @params  = params
      @against = against
    end

    def check!
      unless missing.empty?
        raise ServiceArgumentError, "Missing required params #{missing.inspect}"
      end
      unless extra.empty?
        raise ServiceArgumentError, "Unknown params #{extra.inspect}"
      end
      check_one_required!
    end

    private

    def required
      @required ||= list(@against[:require])
    end

    def allowed
      @allowed ||= allowed_with_dependencies
    end

    def one_required
      @one_required ||= list(@against[:require_one_of])
    end

    def dependencies_allowed
      @dependencies_allowed ||= @against[:allow_dependencies] || {}
    end

    def allowed_with_dependencies
      base = list(@against[:allow])
      dependencies_allowed.each_with_object(base) do |(key, dependent_keys), memo|
        if provided.include?(key)
          memo.push(*list(dependent_keys))
        end
      end
    end

    def provided
      @provided ||= @params.keys.map(&:to_sym)
    end

    def list(candidate)
      Array(candidate).dup.compact
    end

    def missing
      @missing ||= required - provided
    end

    def extra
      @extra ||= provided - (required + allowed + one_required)
    end

    def check_one_required!
      count = one_required_count
      if count
        if count < 1
          raise ServiceArgumentError, "Need exactly one of #{one_required.inspect}"
        elsif count > 1
          raise ServiceArgumentError, "Only one of #{one_required.inspect} allowed"
        end
      end
    end

    def one_required_count
      if one_required.any?
        provided.select { |item| one_required.include?(item) }.size
      end
    end

  end

end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
twfy-1.1.1 lib/twfy/validation.rb
twfy-1.1.0 lib/twfy/validation.rb