Skip to content

Commit

Permalink
Introduce dispatchers for adding syntax sugar to helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
nepalez committed Feb 1, 2018
1 parent 7a605f2 commit ed951c3
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 3 deletions.
5 changes: 3 additions & 2 deletions lib/dry/initializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module Initializer
require_relative "initializer/builders"
require_relative "initializer/config"
require_relative "initializer/mixin"
require_relative "initializer/dispatchers"

# Adds methods [.[]] and [.define]
extend DSL
Expand All @@ -34,7 +35,7 @@ def dry_initializer
# @option opts [true, false, :protected, :public, :private] :reader
# @return [self] itself
def param(name, type = nil, **opts)
dry_initializer.param(name, type, opts)
dry_initializer.param(name, type, Dispatchers[opts])
self
end

Expand All @@ -43,7 +44,7 @@ def param(name, type = nil, **opts)
# @option (see #param)
# @return (see #param)
def option(name, type = nil, **opts)
dry_initializer.option(name, type, opts)
dry_initializer.option(name, type, Dispatchers[opts])
self
end

Expand Down
2 changes: 1 addition & 1 deletion lib/dry/initializer/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def initialize(extended_class = nil, null: UNDEFINED)
end

def add_definition(option, name, type, opts)
definition = Definition.new(option, null, name, type, opts)
definition = Definition.new(option, null, name, type, Dispatchers[opts])
definitions[definition.source] = definition
finalize

Expand Down
44 changes: 44 additions & 0 deletions lib/dry/initializer/dispatchers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Dry::Initializer
#
# @private
#
# Dispatchers allow adding syntax sugar to `.param` and `.option` methods.
#
# Every dispatcher should convert the source hash of options into
# the resulting hash so that you can send additional keys to the helpers.
#
# @example Add special dispatcher
#
# # Define a dispatcher for key :integer
# dispatcher = proc do |opts|
# opts.merge(type: proc(&:to_i)) if opts[:integer]
# end
#
# # Register a dispatcher
# Dry::Initializer::Dispatchers << dispatcher
#
# # Now you can use option `integer: true` instead of `type: proc(&:to_i)`
# class Foo
# extend Dry::Initializer
# param :id, integer: true
# end
#
module Dispatchers
class << self
def <<(item)
list << item
self
end

def [](options)
list.inject(options) { |opts, item| item.call(opts) }
end

private

def list
@list ||= []
end
end
end
end
35 changes: 35 additions & 0 deletions spec/custom_dispatchers_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
describe "custom dispatchers" do
subject { Test::Foo.new "123" }

before do
dispatcher = ->(op) { op[:integer] ? op.merge(type: proc(&:to_i)) : op }
Dry::Initializer::Dispatchers << dispatcher
end

context "with extend syntax" do
before do
class Test::Foo
extend Dry::Initializer
param :id, integer: true
end
end

it "adds syntax sugar" do
expect(subject.id).to eq 123
end
end

context "with include syntax" do
before do
class Test::Foo
include Dry::Initializer.define -> do
param :id, integer: true
end
end
end

it "adds syntax sugar" do
expect(subject.id).to eq 123
end
end
end

0 comments on commit ed951c3

Please sign in to comment.