Skip to content

Commit

Permalink
[WIP] Add initial support for decentralized dispatch tables
Browse files Browse the repository at this point in the history
API can/must be tweaked, but this is a start. Unit
specs fail at this point, integration specs pass
tho.
  • Loading branch information
snusnu committed Jul 31, 2013
1 parent c5548cb commit 5e3d3a6
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 27 deletions.
37 changes: 31 additions & 6 deletions lib/substation/environment.rb
Expand Up @@ -19,11 +19,22 @@ class Environment
# @return [Environment]
#
# @api private
def self.build(other = Undefined, &block)
instance = new(Chain::DSL.build(DSL.registry(&block)))
def self.build(app_env, actions = Dispatcher::Registry.new, other = Undefined, &block)
instance = new(app_env, actions, chain_dsl(&block))
other.equal?(Undefined) ? instance : other.merge(instance)
end

def self.merge(other, &block)
instance = new(other.app_env, other.actions, chain_dsl(&block))
other.merge(instance)
end

def self.chain_dsl(&block)
Chain::DSL.build(DSL.registry(&block))
end

private_class_method :chain_dsl

# The registry used by this {Environment}
#
# @return [Hash<Symbol, Processor::Builder>]
Expand All @@ -32,6 +43,10 @@ def self.build(other = Undefined, &block)
attr_reader :registry
protected :registry

attr_reader :app_env

attr_reader :actions

# Initialize a new instance
#
# @param [Chain::DSL] chain_dsl
Expand All @@ -40,7 +55,9 @@ def self.build(other = Undefined, &block)
# @return [undefined]
#
# @api private
def initialize(chain_dsl)
def initialize(app_env, actions, chain_dsl)
@app_env = app_env
@actions = actions
@chain_dsl = chain_dsl
@registry = chain_dsl.registry
end
Expand All @@ -60,6 +77,14 @@ def chain(other = Chain::EMPTY, failure_chain = Chain::EMPTY, &block)
@chain_dsl.build(other, failure_chain, &block)
end

def register(name, other = Chain::EMPTY, failure_chain = Chain::EMPTY, &block)
@actions[name] = @chain_dsl.build(other, failure_chain, &block)
end

def [](name)
@actions.fetch(name)
end

# Build a new {Action} instance
#
# @param [#call] handler
Expand All @@ -85,8 +110,8 @@ def action(handler, observers = EMPTY_ARRAY)
# @return [Dispatcher]
#
# @api private
def dispatcher(dispatch_table, env)
Dispatcher.new(dispatch_table, env)
def dispatcher
Dispatcher.new(actions, app_env)
end

# Return a new instance that has +other+ merged into +self+
Expand All @@ -99,7 +124,7 @@ def dispatcher(dispatch_table, env)
#
# @api private
def merge(other)
self.class.new(Chain::DSL.build(merged_registry(other)))
self.class.new(app_env, Dispatcher::Registry.new, Chain::DSL.build(merged_registry(other)))
end

private
Expand Down
2 changes: 1 addition & 1 deletion spec/demo/core.rb
Expand Up @@ -38,7 +38,7 @@ class Demo
require 'demo/core/observers'

module Core
ENV = Substation::Environment.build do
ENV = Substation::Environment.build(APP_ENV) do
register :authenticate, Substation::Processor::Evaluator::Request
register :authorize, Substation::Processor::Evaluator::Request
register :validate, Substation::Processor::Evaluator::Request, Core::Validator::EXECUTOR
Expand Down
11 changes: 2 additions & 9 deletions spec/demo/core/facade.rb
Expand Up @@ -25,23 +25,16 @@ module App
authorize Handler::Authorizer, AUTHORIZATION_ERROR
end

CREATE_PERSON = Core::ENV.chain(AUTHORIZE, INTERNAL_ERROR) do
Core::ENV.register(:create_person, AUTHORIZE, INTERNAL_ERROR) do
validate Domain::DTO::NEW_PERSON_VALIDATOR, VALIDATION_ERROR
accept Handler::Acceptor
call Core::CREATE_PERSON, APPLICATION_ERROR
end

end

# This is temporary and will be replaced by self registering
# actions, which will remove the need for a centralized dispatch
# table definition
dispatch_table = Substation::Dispatcher::Registry.new({
:create_person => App::CREATE_PERSON
})

# The application
APP = Core::ENV.dispatcher(dispatch_table, Demo::APP_ENV)
APP = Core::ENV.dispatcher

end
end
2 changes: 1 addition & 1 deletion spec/demo/web.rb
Expand Up @@ -15,7 +15,7 @@

class Demo
module Web
ENV = Substation::Environment.build(Core::ENV) do
ENV = Substation::Environment.merge(Core::ENV) do
register :deserialize, Substation::Processor::Transformer::Incoming, Web::Handler::Deserializer::EXECUTOR
register :sanitize, Substation::Processor::Evaluator::Request, Web::Sanitizer::EXECUTOR
register :wrap, Substation::Processor::Wrapper::Outgoing, Core::Handler::Wrapper::Outgoing::EXECUTOR
Expand Down
13 changes: 3 additions & 10 deletions spec/demo/web/facade.rb
Expand Up @@ -12,7 +12,7 @@ module Web
CREATE_PERSON = Web::ENV.chain do
deserialize Handler::Deserializer
sanitize Sanitizer::NEW_PERSON, SANITIZATION_ERROR
chain Core::App::CREATE_PERSON
chain Core::ENV[:create_person]
end

module HTML
Expand Down Expand Up @@ -42,7 +42,7 @@ module HTML
render Renderer::InternalError
end

CREATE_PERSON = Web::ENV.chain(Web::CREATE_PERSON, INTERNAL_ERROR) do
Web::ENV.register(:create_person, Web::CREATE_PERSON, INTERNAL_ERROR) do
failure_chain :sanitize, SANITIZATION_ERROR
failure_chain :authenticate, AUTHENTICATION_ERROR
failure_chain :authorize, AUTHORIZATION_ERROR
Expand All @@ -52,15 +52,8 @@ module HTML
wrap Views::Person
end

# This is temporary and will be replaced by self registering
# actions, which will remove the need for a centralized dispatch
# table definition
dispatch_table = {
:create_person => CREATE_PERSON
}

# The application
APP = Web::ENV.dispatcher(dispatch_table, APP_ENV)
APP = Web::ENV.dispatcher

end # module HTML
end # module Web
Expand Down

0 comments on commit 5e3d3a6

Please sign in to comment.