1
0
mirror of https://github.com/meineerde/rackstash.git synced 2025-10-17 14:01:01 +00:00

Add Hash#set to set a field from a block if it doesn't exist yet

This allows to define default values for certain fields which can be
inserted just before a Buffer is flushed. They won;t overwrite prior
user-provided fields.

Through the use of a block, expensive calculations for a field could be
avoided if the field is not going to be inserted, e.g. because it exists
already or is forbidden from being set.
This commit is contained in:
Holger Just 2017-02-09 00:15:15 +01:00
parent ea77a8ae26
commit 031198cf14
2 changed files with 60 additions and 0 deletions

View File

@ -183,6 +183,33 @@ module Rackstash
@forbidden_keys.include?(key)
end
# 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
# other than `nil`, the block will not be called and the value will not be
# set.
#
# @param key [#to_s] the field name. When setting the field, this name
# will be normalized as a frozen UTF-8 string.
#
# @yield [key] if the key doesn't exist yet, we call the block and use its
# return value as the value to insert at `key`
# @yieldparam key [String] The normalized key where the value is being
# inserted
# @yieldreturn [Object] the intended new value for `key` to be merged into
# `self` at `key`.
#
# @return [Object, nil] The return value of the block or `nil` if no
# insertion happened. Note that `nil` is also a valid value to insert
# into the hash.
def set(key)
key = utf8_encode(key)
return if forbidden_key?(key)
return unless @raw[key] == nil
@raw[key] = normalize(yield(key))
end
# @return [::Array] a new array populated with the values from this hash.
# @see #keys
def values

View File

@ -317,6 +317,39 @@ describe Rackstash::Fields::Hash do
end
end
describe '#set' do
it 'allows to set a normalized value' do
expect(hash).to receive(:normalize).with(:value).and_call_original
hash.set(:symbol) { :value }
expect(hash['symbol']).to eql 'value'
end
it 'ignores forbidden keys' do
forbidden_keys << 'forbidden'
expect { |b| hash.set(:forbidden, &b) }.not_to yield_control
expect { |b| hash.set('forbidden', &b) }.not_to yield_control
expect(hash['forbidden']).to be_nil
end
it 'ignores existing keys' do
hash['key'] = 'value'
expect { |b| hash.set(:key, &b) }.not_to yield_control
expect { |b| hash.set('key', &b) }.not_to yield_control
expect(hash['key']).to eql 'value'
end
it 'overwrites nil value' do
hash['nil'] = nil
expect { |b| hash.set('nil', &b) }.to yield_control
end
end
describe '#values' do
it 'returns an array of values' do
hash['string'] = 'beep'