1
0
mirror of https://github.com/meineerde/rackstash.git synced 2026-02-27 13:51:45 +00:00

Correctly describe the proc evaluation behavior in Fields

This commit is contained in:
Holger Just 2017-10-06 21:14:35 +02:00
parent 2e7083218c
commit 469ab5823a
3 changed files with 65 additions and 71 deletions

View File

@ -0,0 +1,22 @@
# frozen_string_literal: true
#
# Copyright 2017 Holger Just
#
# This software may be modified and distributed under the terms
# of the MIT license. See the LICENSE.txt file for details.
# This file contains code documentation macros which are used through out the
# Rackstash code base. The file is loaded early in `.yardopts` so that the
# macros defined here should be available everywhere.
# @!macro resolves_procs_with_scope
# If `$1` itself is a `Proc`, we will call it and use the returned value in
# its place. If any of the (deeply nested) values of `$1` is a `Proc`, it will
# likewise be called and the respective return value will be used there.
#
# If you give the optional `scope` argument, each `Proc` object will be called
# with the `scope` object as their only argument. If the `Proc` object doesn't
# accept any arguments it will be executed in the context of the `scope`
# object instead. If you leave the `scope` empty (or set it to `nil`), each
# `Proc` object will be evaluated in the context of their original creation
# environment.

View File

@ -184,11 +184,12 @@ module Rackstash
# Appends the elements of `array` to self.
#
# @macro resolves_procs_with_scope
#
# @param array [Array, ::Array, Proc] an array of values. Each value is
# normalized before being added to `self`.
# @param scope [Object, nil] if `array` or any of its (deeply-nested)
# values is a proc, it will be called in the instance scope of this
# object (when given).
# values is a `Proc`, it will be called with this object (when given)
# @return [self]
def concat(array, scope: nil)
array = implicit(normalize(array, wrap: false, scope: scope))
@ -211,11 +212,12 @@ module Rackstash
# `self` and `array` excluding any duplicates and preserving the order
# from `self`.
#
# @macro resolves_procs_with_scope
#
# @param array [Array, ::Array, Proc] an array of values. Each value is
# normalized before being added to `self`.
# @param scope [Object, nil] if `array` or any of its (deeply-nested)
# values is a proc, it will be called in the instance scope of this
# object (when given).
# values is a `Proc`, it will be called with this object (when given)
# @return [Array]
#
# @see #|
@ -227,11 +229,12 @@ module Rackstash
# Set Union - Add value from `array` to `self` excluding any duplicates
# and preserving the order from `self`.
#
# @macro resolves_procs_with_scope
#
# @param array [Array, ::Array, Proc] an array of values. Each value is
# normalized before being added to `self`.
# @param scope [Object, nil] if `array` or any of its (deeply-nested)
# values is a proc, it will be called in the instance scope of this
# object (when given).
# values is a `Proc`, it will be called with this object (when given)
# @return [self]
#
# @see #merge
@ -251,7 +254,6 @@ module Rackstash
# @return [Object, Array<Object>, nil] If `n` was given, we always return
# an array with at most `n` elements. Else, we return the last element
# or `nil` if the array is empty.
#
def pop(n = nil)
n.nil? ? @raw.pop : @raw.pop(n)
end
@ -260,10 +262,11 @@ module Rackstash
# values will be normalized before being added. This method returns the
# array itself, so several appends may be chained together.
#
# @macro resolves_procs_with_scope
#
# @param values [::Array] a list of values to append at the end of `self`
# @param scope [Object, nil] if any of the (deeply-nested) values is a
# proc, it will be called in the instance scope of this object (when
# given).
# @param scope [Object, nil] if any of the (deeply-nested) values in
# `values` is a `Proc`, it will be called with this object (when given)
# @return [self]
def push(*values, scope: nil)
concat(values, scope: scope)
@ -288,11 +291,12 @@ module Rackstash
# Prepends objects to the front of `self`, moving other elements upwards.
# See also {#shift} for the opposite effect.
#
# @macro resolves_procs_with_scope
#
# @param values [::Array] a list of values to prepend to the front of
# `self`
# @param scope [Object, nil] if any of the (deeply-nested) values is a
# proc, it will be called in the instance scope of this object (when
# given).
# @param scope [Object, nil] if any of the (deeply-nested) values in
# `values` is a `Proc`, it will be called with this object (when given)
# @return [self]
def unshift(*values, scope: nil)
values.map! { |value| normalize(value, scope: scope) }

View File

@ -83,14 +83,7 @@ module Rackstash
# {#merge}, this method deep-merges Hash and Array values if the existing
# and merged values are of the same type.
#
# If the value is a callable object (e.g. a proc or lambda), we will call
# it and use the returned value instead, which must then be a Hash of
# course. If any of the values of the hash is a proc, it will also be
# called and the return value will be used.
#
# If you give the optional `scope` argument, the Procs will be evaluated
# in the instance scope of this object. If you leave the `scope` empty,
# they will be called in the scope of their creation environment.
# @macro resolves_procs_with_scope
#
# The following examples are thus all equivalent:
#
@ -101,7 +94,9 @@ module Rackstash
# merged = hash.deep_merge -> { 'foo' => 'bar' }
# merged = hash.deep_merge -> { 'foo' => -> { 'bar' } }
# merged = hash.deep_merge({ 'foo' => -> { self } }, scope: 'bar')
# merged = hash.deep_merge({ 'foo' => ->(scope) { scope } }, scope: 'bar')
# merged = hash.deep_merge -> { { 'foo' => -> { self } } }, scope: 'bar'
# merged = hash.deep_merge ->(scope) { { 'foo' => ->(scope) { scope } } }, scope: 'bar'
#
# Nested hashes will be deep-merged and all field names will be normalized
# to strings, even on deeper levels. Given an empty Hash, these calls
@ -142,12 +137,13 @@ module Rackstash
# field. When set to `false` we silently ignore new values if they exist
# already or are forbidden from being set.
# @param scope (see #merge)
#
# @yield (see #merge)
# @yieldreturn (see #merge)
# @raise [ArgumentError] if you attempt to set one of the forbidden fields
# and `force` is `true`
# @return [Rackstash::Fields::Hash] a new hash containing the merged
# key-value pairs
# @return [Rackstash::Fields::Hash] a new Rackstash Hash containing the
# merged key-value pairs
#
# @see #merge
# @see #deep_merge!
@ -160,14 +156,7 @@ module Rackstash
# added. In contrast to {#merge!}, this method deep-merges Hash and Array
# values if the existing and merged values are of the same type.
#
# If the value is a callable object (e.g. a proc or lambda), we will call
# it and use the returned value instead, which must then be a Hash of
# course. If any of the values of the hash is a proc, it will also be
# called and the return value will be used.
#
# If you give the optional `scope` argument, the Procs will be evaluated
# in the instance scope of this object. If you leave the `scope` empty,
# they will be called in the scope of their creation environment.
# @macro resolves_procs_with_scope
#
# The following examples are thus all equivalent:
#
@ -178,7 +167,9 @@ module Rackstash
# hash.deep_merge! -> { 'foo' => 'bar' }
# hash.deep_merge! -> { 'foo' => -> { 'bar' } }
# hash.deep_merge!({ 'foo' => -> { self } }, scope: 'bar')
# hash.deep_merge!({ 'foo' => ->(scope) { scope } }, scope: 'bar')
# hash.deep_merge! -> { { 'foo' => -> { self } } }, scope: 'bar'
# hash.deep_merge! ->(scope) { { 'foo' => ->(scope) { scope } } }, scope: 'bar'
#
# Nested hashes will be deep-merged and all field names will be normalized
# to strings, even on deeper levels. Given an empty Hash, these calls
@ -219,6 +210,7 @@ module Rackstash
# field. When set to `false` we silently ignore new values if they exist
# already or are forbidden from being set.
# @param scope (see #merge!)
#
# @yield (see #merge!)
# @yieldreturn (see #merge!)
# @raise [ArgumentError] if you attempt to set one of the forbidden fields
@ -272,17 +264,15 @@ module Rackstash
# Returns a new {Hash} containing the contents of `hash` and of
# `self`. If no block is specified, the value for entries with duplicate
# keys will be that of hash. Otherwise the value for each duplicate key
# keys will be that of `hash`. Otherwise the value for each duplicate key
# is determined by calling the block with the `key`, its value in `self`
# and its value in `hash`.
#
# If there are any forbidden fields defined on `self`, An `ArgumentError`
# is raised when trying to set any of these. The values are ignored of
# `force` is set to `false`.
# @macro resolves_procs_with_scope
#
# If `hash` itself of any of its (deeply-nested) values is a proc, it will
# get called and its result will be used instead of it. The proc will be
# evaluated in the instance scope of `scope` if given.
# If there are any forbidden fields defined on `self`, An `ArgumentError`
# is raised when trying to set any of these. The values are ignored if
# `force` is set to `false`.
#
# @param hash [::Hash<#to_s, => Proc, Object>, Rackstash::Fields::Hash, Proc]
# the hash to merge into `self`. If this is a proc, it will get called
@ -292,8 +282,7 @@ module Rackstash
# forbidden key. If `false`, we silently ignore values for existing or
# forbidden keys.
# @param scope [Object, nil] if `hash` or any of its (deeply-nested)
# values is a proc, it will be called in the instance scope of this
# object (when given).
# values is a `Proc`, it will be called with this object (when given)
#
# @yield [key, old_val, new_val] if a block is given and there is a
# duplicate key, we call the block and use its return value as the value
@ -303,11 +292,11 @@ module Rackstash
# @yieldparam new_val [Object] The new normalized value for `key` in
# `hash`
# @yieldreturn [Object] the intended new value for `key` to be merged into
# `self` at `key`. The value will be normalized under the given `scope`.
# `self`. The value will be normalized under the given `scope`.
# @raise [ArgumentError] if you attempt to set one of the forbidden fields
# and `force` is `true`
# @return [Rackstash::Fields::Hash] a new hash containing the merged
# key-value pairs
# @return [Rackstash::Fields::Hash] a new Rackstash `Hash` containing the
# merged key-value pairs
def merge(hash, force: true, scope: nil)
if block_given?
dup.merge!(hash, force: force, scope: scope) { |key, old_val, new_val|
@ -321,6 +310,8 @@ module Rackstash
# Adds the contents of `hash` to `self`. `hash` is normalized before being
# added.
#
# @macro resolves_procs_with_scope
#
# If there are any forbidden keys defined on `self`, {#merge!} will raise
# an `ArgumentError` when trying to set any of these. The keys are
# silently ignored if `force` is set to `false`.
@ -335,15 +326,6 @@ module Rackstash
# the value from `hash`. If `force` is false, we use the existing value in
# `self` if it is not `nil`.
#
# If `hash` itself of any of its (deeply-nested) values is a callable
# object (e.g. a proc or lambda) we call it and use its normalized result
# instead of the proc.
#
# If you give the optional `scope` argument, the Procs will be evaluated
# in the instance scope of the `scope` object. If you leave the `scope`
# empty, Procs will be called in the scope of their closure (creation
# environment).
#
# @param hash [::Hash<#to_s, => Proc, Object>, Rackstash::Fields::Hash, Proc]
# the hash to merge into `self`. If this is a proc, it will get called
# and its result is used instead
@ -352,8 +334,7 @@ module Rackstash
# forbidden key. If `false`, we silently ignore values for existing or
# forbidden keys.
# @param scope [Object, nil] if `hash` or any of its (deeply-nested)
# values is a proc, it will be called in the instance scope of this
# object (when given).
# values is a `Proc`, it will be called with this object (when given)
#
# @yield [key, old_val, new_val] if a block is given and there is a
# duplicate key, we call the block and use its return value as the value
@ -363,7 +344,7 @@ module Rackstash
# @yieldparam new_val [Object] The new normalized value for `key` in
# `hash`
# @yieldreturn [Object] the intended new value for `key` to be merged into
# `self` at `key`. The value will be normalized under the given `scope`.
# `self`. The value will be normalized under the given `scope`.
# @raise [ArgumentError] if you attempt to set one of the forbidden fields
# and `force` is `true`
# @return [self]
@ -400,14 +381,7 @@ module Rackstash
# {#merge}, this method preserves any non-nil values of existing keys in
# `self` in the returned hash.
#
# If `hash` is a callable object (e.g. a proc or lambda), we will call
# it and use the returned value instead, which must then be a Hash of
# course. If any of the values of the hash is a proc, it will also be
# called and the return value will be used.
#
# If you give the optional `scope` argument, the Procs will be evaluated
# in the instance scope of this object. If you leave the `scope` empty,
# they will be called in the scope of their creation environment.
# @macro resolves_procs_with_scope
#
# @param hash (see #merge)
# @param scope (see #merge)
@ -424,14 +398,7 @@ module Rackstash
# added. `hash` is normalized before being added. In contrast to {#merge},
# this method preserves any non-nil values of existing keys in `self`.
#
# If `hash` is a callable object (e.g. a proc or lambda), we will call
# it and use the returned value instead, which must then be a Hash of
# course. If any of the values of the hash is a proc, it will also be
# called and the return value will be used.
#
# If you give the optional `scope` argument, the Procs will be evaluated
# in the instance scope of this object. If you leave the `scope` empty,
# they will be called in the scope of their creation environment.
# @macro resolves_procs_with_scope
#
# @param hash (see #merge!)
# @param scope (see #merge!)
@ -502,6 +469,7 @@ module Rackstash
# merge operation, usually either `:merge` or `:merge!`
# @param force [Boolean] set to `true` to overwrite keys with divering
# value types, or `false` to silently ignore the new value
# @param scope [Object, nil] the object to evaluate Proc objects with
# @return [Lambda] a resolver block for deep-merging a hash.
def deep_merge_resolver(merge_method, force: true, scope: nil)
resolver = lambda do |key, old_val, new_val|