Skip to content

Commit

Permalink
Merge pull request #463 from dry-rb/460-461-expand-result-api
Browse files Browse the repository at this point in the history
Add Result#[]= and Result#key?
  • Loading branch information
solnic authored Mar 4, 2019
2 parents 596398c + 074a48a commit a4b0ca8
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 1 deletion.
34 changes: 33 additions & 1 deletion lib/dry/validation/result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,32 @@ def add_error(key, message)
#
# @api public
def [](key)
values[key]
values.key?(key) && values[key] || storage.key?(key) && storage[key]
end

# Store value under specified key
#
# @param [Symbol] key
# @param [Object] value
#
# @return [Object]
#
# @api public
def []=(key, value)
raise ArgumentError, "Key +#{key}+ was already set" if key?(key)

storage[key] = value
end

# Check if a key was set
#
# @param [Symbol] key
#
# @return [Bool]
#
# @api public
def key?(key)
values.key?(key) || storage.key?(key)
end

# Coerce to a hash
Expand All @@ -110,6 +135,13 @@ def update(new_errors)
def inspect
"#<#{self.class}#{to_h.inspect} errors=#{errors.inspect}>"
end

private

# @api private
def storage
@storage ||= EMPTY_HASH.dup
end
end
end
end
49 changes: 49 additions & 0 deletions spec/integration/contract/evaluator/setting_values_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

RSpec.describe Dry::Validation::Evaluator, 'values writer' do
context 'when key does not exist' do
subject(:contract) do
Dry::Validation::Contract.build do
schema do
required(:email).filled(:string)
required(:user_id).filled(:integer)
end

rule(:user_id) do
if values[:user_id].equal?(312)
values[:user] = 'jane'
else
failure(:user, 'must be jane')
end
end

rule(:email) do
failure('is invalid') if values[:user] == 'jane' && values[:email] != '[email protected]'
end
end
end

it 'stores new values between rule execution' do
expect(contract.(user_id: 3, email: '[email protected]').errors).to eql(user: ['must be jane'])
expect(contract.(user_id: 312, email: '[email protected]').errors).to eql(email: ['is invalid'])
end
end

context 'when key already exists' do
subject(:contract) do
Dry::Validation::Contract.build do
schema do
required(:email).filled(:string)
end

rule(:email) do
values[:email] = 'foo'
end
end
end

it 'raises error' do
expect { contract.(email: '[email protected]') }.to raise_error(ArgumentError, /email/)
end
end
end

0 comments on commit a4b0ca8

Please sign in to comment.