Skip to content

Commit ed951c3

Browse files
committed
Introduce dispatchers for adding syntax sugar to helpers
1 parent 7a605f2 commit ed951c3

File tree

4 files changed

+83
-3
lines changed

4 files changed

+83
-3
lines changed

lib/dry/initializer.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module Initializer
1414
require_relative "initializer/builders"
1515
require_relative "initializer/config"
1616
require_relative "initializer/mixin"
17+
require_relative "initializer/dispatchers"
1718

1819
# Adds methods [.[]] and [.define]
1920
extend DSL
@@ -34,7 +35,7 @@ def dry_initializer
3435
# @option opts [true, false, :protected, :public, :private] :reader
3536
# @return [self] itself
3637
def param(name, type = nil, **opts)
37-
dry_initializer.param(name, type, opts)
38+
dry_initializer.param(name, type, Dispatchers[opts])
3839
self
3940
end
4041

@@ -43,7 +44,7 @@ def param(name, type = nil, **opts)
4344
# @option (see #param)
4445
# @return (see #param)
4546
def option(name, type = nil, **opts)
46-
dry_initializer.option(name, type, opts)
47+
dry_initializer.option(name, type, Dispatchers[opts])
4748
self
4849
end
4950

lib/dry/initializer/config.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def initialize(extended_class = nil, null: UNDEFINED)
135135
end
136136

137137
def add_definition(option, name, type, opts)
138-
definition = Definition.new(option, null, name, type, opts)
138+
definition = Definition.new(option, null, name, type, Dispatchers[opts])
139139
definitions[definition.source] = definition
140140
finalize
141141

lib/dry/initializer/dispatchers.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
module Dry::Initializer
2+
#
3+
# @private
4+
#
5+
# Dispatchers allow adding syntax sugar to `.param` and `.option` methods.
6+
#
7+
# Every dispatcher should convert the source hash of options into
8+
# the resulting hash so that you can send additional keys to the helpers.
9+
#
10+
# @example Add special dispatcher
11+
#
12+
# # Define a dispatcher for key :integer
13+
# dispatcher = proc do |opts|
14+
# opts.merge(type: proc(&:to_i)) if opts[:integer]
15+
# end
16+
#
17+
# # Register a dispatcher
18+
# Dry::Initializer::Dispatchers << dispatcher
19+
#
20+
# # Now you can use option `integer: true` instead of `type: proc(&:to_i)`
21+
# class Foo
22+
# extend Dry::Initializer
23+
# param :id, integer: true
24+
# end
25+
#
26+
module Dispatchers
27+
class << self
28+
def <<(item)
29+
list << item
30+
self
31+
end
32+
33+
def [](options)
34+
list.inject(options) { |opts, item| item.call(opts) }
35+
end
36+
37+
private
38+
39+
def list
40+
@list ||= []
41+
end
42+
end
43+
end
44+
end

spec/custom_dispatchers_spec.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
describe "custom dispatchers" do
2+
subject { Test::Foo.new "123" }
3+
4+
before do
5+
dispatcher = ->(op) { op[:integer] ? op.merge(type: proc(&:to_i)) : op }
6+
Dry::Initializer::Dispatchers << dispatcher
7+
end
8+
9+
context "with extend syntax" do
10+
before do
11+
class Test::Foo
12+
extend Dry::Initializer
13+
param :id, integer: true
14+
end
15+
end
16+
17+
it "adds syntax sugar" do
18+
expect(subject.id).to eq 123
19+
end
20+
end
21+
22+
context "with include syntax" do
23+
before do
24+
class Test::Foo
25+
include Dry::Initializer.define -> do
26+
param :id, integer: true
27+
end
28+
end
29+
end
30+
31+
it "adds syntax sugar" do
32+
expect(subject.id).to eq 123
33+
end
34+
end
35+
end

0 commit comments

Comments
 (0)