mirror of
https://github.com/meineerde/rackstash.git
synced 2025-12-19 15:01:12 +00:00
Add Fields::Hash#reverse_merge and reverse_merge! similar to the ActiveSupport methods on Hash
This commit is contained in:
parent
2070bf81a7
commit
bfa5e33c04
@ -343,6 +343,66 @@ module Rackstash
|
|||||||
end
|
end
|
||||||
alias update merge!
|
alias update merge!
|
||||||
|
|
||||||
|
|
||||||
|
# Returns a new {Hash} containing the contents of `hash` and the contents
|
||||||
|
# of `self`. `hash` is normalized before being added. In contrast to
|
||||||
|
# {#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.
|
||||||
|
#
|
||||||
|
# @param hash (see #merge)
|
||||||
|
# @param scope (see #merge)
|
||||||
|
# @return [Rackstash::Fields::Hash] a new hash containing the merged
|
||||||
|
# key-value pairs
|
||||||
|
#
|
||||||
|
# @see #merge
|
||||||
|
# @see #reverse_merge!
|
||||||
|
def reverse_merge(hash, scope: nil)
|
||||||
|
merge(hash, force: false, scope: scope) { |_key, old_val, new_val|
|
||||||
|
old_val == nil ? new_val : old_val
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
# Adds the contents of `hash` to `self`. `hash` is normalized before being
|
||||||
|
# added. In contrast to {#merge!}, this method deep-merges Hash and Array
|
||||||
|
# values if the existing and merged values are of the same type.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Returns a new {Hash} containing the contents of `hash` and the contents
|
||||||
|
# of `self`. `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.
|
||||||
|
#
|
||||||
|
# @param hash (see #merge!)
|
||||||
|
# @param scope (see #merge!)
|
||||||
|
# @return [self]
|
||||||
|
#
|
||||||
|
# @see #merge!
|
||||||
|
# @see #reverse_merge
|
||||||
|
def reverse_merge!(hash, scope: nil)
|
||||||
|
merge!(hash, force: false, scope: scope) { |_key, old_val, new_val|
|
||||||
|
old_val == nil ? new_val : old_val
|
||||||
|
}
|
||||||
|
end
|
||||||
|
alias reverse_update reverse_merge!
|
||||||
|
|
||||||
# Set a `key` of `self` to the returned value of the passed block.
|
# Set a `key` of `self` to the returned value of the passed block.
|
||||||
# If the key is forbidden from being set or already exists with a value
|
# If the key is forbidden from being set or already exists with a value
|
||||||
# other than `nil`, the block will not be called and the value will not be
|
# other than `nil`, the block will not be called and the value will not be
|
||||||
|
|||||||
@ -510,6 +510,82 @@ describe Rackstash::Fields::Hash do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#reverse_merge' do
|
||||||
|
before do
|
||||||
|
hash['foo'] = 'bar'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a new hash' do
|
||||||
|
expect(hash.reverse_merge(foo: :baz, beep: :boop)).not_to equal hash
|
||||||
|
expect(hash).not_to include 'beep'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not overwrite existing values' do
|
||||||
|
expect(hash.reverse_merge(foo: :baz, beep: :boop)['foo']).to eql 'bar'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'adds new values' do
|
||||||
|
expect(hash.reverse_merge(foo: :baz, beep: :boop)['beep']).to eql 'boop'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'evaluates procs' do
|
||||||
|
expect(hash.reverse_merge(-> { { beep: -> { self } } }, scope: 42)['beep'])
|
||||||
|
.to eql 42
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'overwrites nil values' do
|
||||||
|
hash['beep'] = nil
|
||||||
|
expect(hash).to include 'beep'
|
||||||
|
|
||||||
|
expect(hash.reverse_merge(beep: :boop)['beep']).to eql 'boop'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'raises an error for non-hash arguments' do
|
||||||
|
expect { hash.reverse_merge [] }.to raise_error TypeError
|
||||||
|
expect { hash.reverse_merge nil }.to raise_error TypeError
|
||||||
|
expect { hash.reverse_merge false }.to raise_error TypeError
|
||||||
|
expect { hash.reverse_merge 'value' }.to raise_error TypeError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#reverse_merge!' do
|
||||||
|
before do
|
||||||
|
hash['foo'] = 'bar'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'mutates the existing hash' do
|
||||||
|
expect(hash.reverse_merge!(foo: :baz, beep: :boop)).to equal hash
|
||||||
|
expect(hash).to include 'beep'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not overwrite existing values' do
|
||||||
|
expect(hash.reverse_merge!(foo: :baz, beep: :boop)['foo']).to eql 'bar'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'adds new values' do
|
||||||
|
expect(hash.reverse_merge!(foo: :baz, beep: :boop)['beep']).to eql 'boop'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'evaluates procs' do
|
||||||
|
expect(hash.reverse_merge!(-> { { beep: -> { self } } }, scope: 42)['beep'])
|
||||||
|
.to eql 42
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'overwrites nil values' do
|
||||||
|
hash['beep'] = nil
|
||||||
|
expect(hash).to include 'beep'
|
||||||
|
|
||||||
|
expect(hash.reverse_merge!(beep: :boop)['beep']).to eql 'boop'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'raises an error for non-hash arguments' do
|
||||||
|
expect { hash.reverse_merge! [] }.to raise_error TypeError
|
||||||
|
expect { hash.reverse_merge! nil }.to raise_error TypeError
|
||||||
|
expect { hash.reverse_merge! false }.to raise_error TypeError
|
||||||
|
expect { hash.reverse_merge! 'value' }.to raise_error TypeError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#set' do
|
describe '#set' do
|
||||||
it 'allows to set a normalized value' do
|
it 'allows to set a normalized value' do
|
||||||
expect(hash).to receive(:normalize).with(:value).and_call_original
|
expect(hash).to receive(:normalize).with(:value).and_call_original
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user