Skip to content

Commit

Permalink
Merge pull request #52 from pabloh/improve_state_use
Browse files Browse the repository at this point in the history
Improve State#use to accept positional params
  • Loading branch information
pabloh authored Aug 11, 2024
2 parents df14f99 + cc2d808 commit 6154b70
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## [0.12.3] - 2024-08-07
### Changed
- Renamed config option `:auto_wire_options` to `:auto_wire` at `:dry_validation` plugin
- Updated `Pathway::State#unwrap` to accept block with postional parameters
- Updated `Pathway::State#unwrap` to raise an `ArgumentError` exception on invalid arguments
### Added
- Provide alias `Pathway::State#use` to `Pathway::State#unwrap`
Expand Down
17 changes: 10 additions & 7 deletions lib/pathway.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,19 @@ def to_hash

def use(&bl)
raise ArgumentError, 'a block must be provided' if !block_given?
if bl.parameters.any? {|(type,_)| type == :keyrest || type == :rest }
raise ArgumentError, 'rest arguments are not supported'
end

params = bl.parameters
keys = bl.parameters.select {|(type,_)| type == :key || type == :keyreq }.map(&:last)
names = bl.parameters.select {|(type,_)| type == :req || type == :opt }.map(&:last)

if !params.all? { |(type,_)| [:block, :key, :keyreq, :keyrest].member?(type) }
raise ArgumentError, 'only keyword arguments are supported'
elsif params.any? {|(type,_)| type == :keyrest }
bl.call(**to_hash)
else
keys = params.select {|(type,_)| type == :key || type == :keyreq }.map(&:last)
if keys.any? && names.any?
raise ArgumentError, 'cannot mix positional and keyword arguments'
elsif keys.any?
bl.call(**to_hash.slice(*keys))
else
bl.call(*to_hash.values_at(*names))
end
end

Expand Down
51 changes: 33 additions & 18 deletions spec/state_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,43 +34,58 @@ class SimpleOp < Operation
end

context 'when a block is provided' do
it 'passes specified values by the keyword params', :aggregate_failures do
it 'passes specified values using only keyword params', :aggregate_failures do
expect(state.unwrap {|val:| val }).to eq('RESULT')
expect(state.unwrap {|foo:| foo }).to eq(99)
expect(state.unwrap {|val:, bar:| [val, bar] })
.to eq(['RESULT', 131])
end

it 'passes all values if **kwargs is part of the params', :aggregate_failures do
expect(state.unwrap {|**kargs| kargs })
.to eq(foo: 99, bar: 131, val: 'RESULT', input: 'some value')
expect(state.unwrap {|input:, **kargs| input }).to eq('some value')
expect(state.unwrap {|input:, **kargs| kargs })
.to eq(foo: 99, bar: 131, val: 'RESULT')
it 'passes no arguments if no keyword or positional params are defined' do
expect(state.unwrap { 77 }).to eq(77)
end

it 'passes no arguments if no keyword params are defined' do
expect(state.unwrap { 77 }).to eq(77)
it 'passes specified values using only positional params', :aggregate_failures do
expect(state.unwrap {|val| val }).to eq('RESULT')
expect(state.unwrap {|foo| foo }).to eq(99)
expect(state.unwrap {|val, bar| [val, bar] })
end

it 'fails if at least one positional param is defined', :aggregate_failures do
it 'fails if positional and keyword params are both defined', :aggregate_failures do
expect { state.unwrap {|pos, input:| } }
.to raise_error('only keyword arguments are supported')
expect { state.unwrap {|input| } }
.to raise_error('only keyword arguments are supported')
.to raise_error('cannot mix positional and keyword arguments')
end

it 'fails if using rest param', :aggregate_failures do
expect { state.unwrap {|*input| } }
.to raise_error('rest arguments are not supported')
expect { state.unwrap {|input, *args| args } }
.to raise_error('rest arguments are not supported')
end

context 'and it takes a block argument' do
it 'fails if it has positional params' do
expect { state.unwrap {|input, &bl| } }
.to raise_error('only keyword arguments are supported')
it 'fails if using keyrest param', :aggregate_failures do
expect { state.unwrap {|**kargs| kargs } }
.to raise_error('rest arguments are not supported')
expect { state.unwrap {|input:, **kargs| kargs } }
.to raise_error('rest arguments are not supported')
end

context 'that takes a block argument' do
it 'fails if it has positional and keyword params' do
expect { state.unwrap {|input, val:, &bl| } }
.to raise_error('cannot mix positional and keyword arguments')
end

it 'does not fails if only keyword params', :aggregate_failures do
it 'does not fails if only has keyword params', :aggregate_failures do
expect(state.unwrap {|val:, &bl| val }).to eq('RESULT')
expect(state.unwrap {|val:, &_| val }).to eq('RESULT')
expect(state.unwrap {|&_| 77 }).to eq(77)
end

it 'does not fails if only has positional params', :aggregate_failures do
expect(state.unwrap {|val, &bl| val }).to eq('RESULT')
expect(state.unwrap {|val, &_| val }).to eq('RESULT')
end
end

end
Expand Down

0 comments on commit 6154b70

Please sign in to comment.