Skip to content

Commit bcbd008

Browse files
committed
Allow second parameter for the instance in type coercers
1 parent 78bc066 commit bcbd008

File tree

4 files changed

+70
-4
lines changed

4 files changed

+70
-4
lines changed

CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,35 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

8+
## [2.3.0] [WIP]
9+
10+
### Added
11+
- Type coercer can take second argument for the initialized instance (nepalez)
12+
This allows to wrap assigned value to the object that refers back
13+
to the initializer instance. More verbose example:
14+
15+
```ruby
16+
class Location < String
17+
attr_reader :parameter # refers back to its parameter
18+
19+
def initialize(name, parameter)
20+
super(name)
21+
@parameter = parameter
22+
end
23+
end
24+
25+
class Parameter
26+
extend Dry::Initializer
27+
param :name
28+
param :location, ->(value, param) { Location.new(value, param) }
29+
end
30+
31+
offset = Parameter.new "offset", location: "query"
32+
offset.name # => "offset"
33+
offset.location # => "query"
34+
offset.location.parameter == offset # true
35+
```
36+
837
## [2.2.0] [2017-09-13]
938

1039
### Added
@@ -711,3 +740,4 @@ First public release
711740
[2.0.0]: https://github.com/dry-rb/dry-initializer/compare/v1.4.1...v2.0.0
712741
[2.1.0]: https://github.com/dry-rb/dry-initializer/compare/v2.0.0...v2.1.0
713742
[2.2.0]: https://github.com/dry-rb/dry-initializer/compare/v2.1.0...v2.2.0
743+
[2.3.0]: https://github.com/dry-rb/dry-initializer/compare/v2.2.0...v2.3.0

lib/dry/initializer/builders/attribute.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,12 @@ def default_line
6565

6666
def coercion_line
6767
return unless @type
68-
"#{@val} = #{@item}.type.call(#{@val}) unless #{@val} == #{@null}"
68+
arity = @type.is_a?(Proc) ? @type.arity : @type.method(:call).arity
69+
if arity.abs == 1
70+
"#{@val} = #{@item}.type.call(#{@val}) unless #{@val} == #{@null}"
71+
else
72+
"#{@val} = #{@item}.type.call(#{@val}, self) unless #{@val} == #{@null}"
73+
end
6974
end
7075

7176
def assignment_line

lib/dry/initializer/definition.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,11 @@ def check_target(value)
8181

8282
def check_type(value)
8383
return if value.nil?
84-
arity = value.respond_to?(:call) ? value.method(:call).arity : 0
85-
return value unless arity.zero? || arity > 1
84+
arity = value.arity if value.is_a? Proc
85+
arity ||= value.method(:call).arity if value.respond_to? :call
86+
return value if [1, 2].include? arity.to_i.abs
8687
raise TypeError,
87-
"type of #{inspect} should respond to #call with one argument"
88+
"type of #{inspect} should respond to #call with 1..2 arguments"
8889
end
8990

9091
def check_default(value)

spec/type_constraint_spec.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,36 @@
11
require "dry-types"
22

33
describe "type constraint" do
4+
context "by a proc with 1 argument" do
5+
before do
6+
class Test::Foo
7+
extend Dry::Initializer
8+
param :foo, proc(&:to_s), optional: true
9+
end
10+
end
11+
12+
subject { Test::Foo.new :foo }
13+
14+
it "coerces a value" do
15+
expect(subject.foo).to eq "foo"
16+
end
17+
end
18+
19+
context "by a proc with 2 arguments" do
20+
before do
21+
class Test::Foo
22+
extend Dry::Initializer
23+
param :foo, proc { |val, obj| "#{obj.hash}:#{val}" }, optional: true
24+
end
25+
end
26+
27+
subject { Test::Foo.new :foo }
28+
29+
it "coerces a value with self as a second argument" do
30+
expect(subject.foo).to eq "#{subject.hash}:foo"
31+
end
32+
end
33+
434
context "by dry-type" do
535
before do
636
class Test::Foo

0 commit comments

Comments
 (0)