Sha256: e237cfc5f4c434dd7a31499d3d00e5d8412962fe4559f1a61e290f8a20c70d96

Contents?: true

Size: 1.78 KB

Versions: 72

Compression:

Stored size: 1.78 KB

Contents

# frozen_string_literal: true

class ReeHash::Slice
  include Ree::FnDSL

  fn :slice do
    link :build_filter_keys
    link 'ree_hash/contracts/hash_keys_contract', -> { HashKeysContract }
    def_error { MissingKeyErr }
    def_error { InvalidFilterKey }
  end

  doc(<<~DOC)
    Replaces the hash with only the given keys.
    Returns a hash containing the removed key/value pairs.
    
      hash = { a: 1, b: {e: 2, f: 1}, c: 3, d: 4 }
      slice(hash, [:a, :b])  # => {a: 1, b: 2}
      slice(hash, [:a, b: [:e]])  # => {a: 1, b: {e: 2}}
  DOC

  contract(
    Hash,
    HashKeysContract,
    Ksplat[
      raise?: Bool
    ] => Hash
  ).throws(MissingKeyErr, InvalidFilterKey)
  def call(hash, keys, **opts)
    filter_keys = build_filter_keys(keys)
    recursively_slice(hash, filter_keys, !!opts[:raise])
  end

  private

  def recursively_slice(hash, filter_keys, raise_if_missing)
    result = {}

    filter_keys.each do |filter_k, filter_v|
      if !hash.has_key?(filter_k)
        if raise_if_missing
          raise MissingKeyErr.new("missing key `#{filter_k.inspect}`")
        else
          next
        end
      end

      value = hash[filter_k]

      if filter_v.empty?
        result[filter_k] = value
        next
      end

      if value.is_a?(Array)
        result[filter_k] = value.map do |v|
          if v.is_a?(Hash)
            recursively_slice(v, filter_v, raise_if_missing)
          else
            raise InvalidFilterKey.new("invalid filter key #{filter_v.inspect} for value: #{v.inspect}")
          end
        end
      elsif value.is_a?(Hash)
        result[filter_k] = recursively_slice(value, filter_v, raise_if_missing)
      else
        raise InvalidFilterKey.new("invalid filter key #{filter_v.inspect} for value: #{value.inspect}")
      end
    end

    result
  end
end

Version data entries

72 entries across 72 versions & 1 rubygems

Version Path
ree_lib-1.0.72 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.71 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.70 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.69 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.68 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.67 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.66 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.65 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.64 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.63 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.62 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.61 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.60 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.59 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.58 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.57 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.56 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.55 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.54 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb
ree_lib-1.0.53 lib/ree_lib/packages/ree_hash/package/ree_hash/functions/slice.rb