controll 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +253 -93
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/controll.gemspec +121 -84
- data/lib/controll/assistant/param_assistant.rb +23 -0
- data/lib/controll/assistant/session_assistant.rb +23 -0
- data/lib/controll/assistant.rb +9 -7
- data/lib/controll/commander.rb +16 -3
- data/lib/controll/enabler/macros.rb +75 -0
- data/lib/controll/enabler/maps.rb +15 -0
- data/lib/controll/enabler/notify.rb +43 -0
- data/lib/controll/enabler/path_handler.rb +49 -0
- data/lib/controll/enabler/path_resolver.rb +47 -0
- data/lib/controll/enabler.rb +49 -0
- data/lib/controll/engine.rb +9 -0
- data/lib/controll/errors.rb +4 -1
- data/lib/controll/event/helper.rb +20 -0
- data/lib/controll/{helper/event_matcher.rb → event/matcher.rb} +3 -3
- data/lib/controll/event.rb +60 -0
- data/lib/controll/events.rb +48 -0
- data/lib/controll/executor/base.rb +3 -7
- data/lib/controll/executor/controlled.rb +36 -0
- data/lib/controll/executor/delegator.rb +6 -0
- data/lib/controll/executor.rb +8 -1
- data/lib/controll/flow/action/base.rb +30 -0
- data/lib/controll/flow/action/fallback.rb +25 -0
- data/lib/controll/flow/action/path_action.rb +24 -0
- data/lib/controll/flow/action.rb +7 -0
- data/lib/controll/flow/action_mapper/base.rb +13 -0
- data/lib/controll/flow/action_mapper/complex.rb +52 -0
- data/lib/controll/flow/action_mapper/simple.rb +54 -0
- data/lib/controll/flow/action_mapper.rb +7 -0
- data/lib/controll/flow/errors.rb +16 -0
- data/lib/controll/flow/event_mapper/path_finder.rb +36 -0
- data/lib/controll/flow/event_mapper/util.rb +43 -0
- data/lib/controll/flow/event_mapper.rb +6 -0
- data/lib/controll/flow/master/executor.rb +57 -0
- data/lib/controll/flow/master/macros.rb +66 -0
- data/lib/controll/flow/master.rb +70 -0
- data/lib/controll/flow.rb +15 -0
- data/lib/controll/focused/enabler.rb +31 -0
- data/lib/controll/helper.rb +0 -94
- data/lib/controll/macros.rb +12 -0
- data/lib/controll/notify/base.rb +22 -43
- data/lib/controll/notify/flash.rb +3 -3
- data/lib/controll/notify/macros.rb +57 -0
- data/lib/controll/notify/message/handler.rb +36 -0
- data/lib/controll/notify/message/resolver.rb +28 -0
- data/lib/controll/notify/message/translator.rb +45 -0
- data/lib/controll/notify/message.rb +25 -0
- data/lib/controll/notify/typed.rb +13 -22
- data/lib/controll/notify.rb +11 -4
- data/lib/controll.rb +8 -2
- data/lib/generators/controll/assistant_generator.rb +27 -0
- data/lib/generators/controll/executor_generator.rb +23 -0
- data/lib/generators/controll/flow_handler_generator.rb +21 -0
- data/lib/generators/controll/notifier_generator.rb +21 -0
- data/lib/generators/controll/setup_generator.rb +37 -0
- data/lib/generators/controll/templates/assistant.tt +10 -0
- data/lib/generators/controll/templates/commander.tt +15 -0
- data/lib/generators/controll/templates/executor.tt +14 -0
- data/lib/generators/controll/templates/flow_handler.tt +26 -0
- data/lib/generators/controll/templates/notifier.tt +31 -0
- data/spec/acceptance/app_test.rb +1 -1
- data/spec/controll/assistant/param_assistant_spec.rb +31 -0
- data/spec/controll/assistant/session_assistant_spec.rb +31 -0
- data/spec/controll/assistant_spec.rb +26 -0
- data/spec/controll/command_spec.rb +4 -4
- data/spec/controll/enabler/macros_spec.rb +76 -0
- data/spec/controll/enabler/maps_spec.rb +31 -0
- data/spec/controll/{helper → enabler}/notify_spec.rb +7 -17
- data/spec/controll/enabler/path_handler_spec.rb +24 -0
- data/spec/controll/enabler/path_resolver_spec.rb +87 -0
- data/spec/controll/enabler_spec.rb +30 -0
- data/spec/controll/event/helper_spec.rb +33 -0
- data/spec/controll/{helper/event_matcher_spec.rb → event/matcher_spec.rb} +4 -3
- data/spec/controll/event_spec.rb +66 -0
- data/spec/controll/events_spec.rb +23 -0
- data/spec/controll/executor/controlled_spec.rb +36 -0
- data/spec/controll/executor/{notificator_spec.rb → delegator_spec.rb} +4 -4
- data/spec/controll/flow/action_mapper/complex_spec.rb +102 -0
- data/spec/controll/flow/action_mapper/fallback_spec.rb +34 -0
- data/spec/controll/{flow_handler/render_spec.rb → flow/action_mapper/simple_spec.rb} +25 -22
- data/spec/controll/{flow_handler/redirect/action_spec.rb → flow/event_mapper/path_finder_spec.rb} +10 -10
- data/spec/controll/{flow_handler/redirect/mapper_spec.rb → flow/event_mapper/util_spec.rb} +9 -9
- data/spec/controll/flow/master/executor_spec.rb +56 -0
- data/spec/{app/app/models/.gitkeep → controll/flow/master/macros_spec.rb} +0 -0
- data/spec/controll/flow/master_spec.rb +157 -0
- data/spec/controll/notify/base_spec.rb +6 -12
- data/spec/controll/notify/message/handler_spec.rb +27 -0
- data/spec/controll/notify/message/resolver_spec.rb +53 -0
- data/spec/controll/notify/message/translator_spec.rb +46 -0
- data/spec/controll/notify/message_spec.rb +4 -0
- data/spec/controll/notify/{message_handler.rb → services_notifier.rb} +3 -5
- data/spec/controll/notify/typed_spec.rb +2 -2
- data/spec/{app → controll_app}/.gitignore +0 -0
- data/spec/{app → controll_app}/Gemfile +0 -0
- data/spec/{app → controll_app}/Gemfile.lock +0 -0
- data/spec/{app → controll_app}/README.rdoc +0 -0
- data/spec/{app → controll_app}/Rakefile +0 -0
- data/spec/controll_app/app/controll/commanders/services_commander.rb +5 -0
- data/spec/controll_app/app/controll/executors/services_executor.rb +4 -0
- data/spec/controll_app/app/controll/flows/create_services.rb +9 -0
- data/spec/controll_app/app/controll/notifiers/services_notifier.rb +9 -0
- data/spec/{app → controll_app}/app/controllers/application_controller.rb +0 -1
- data/spec/controll_app/app/controllers/services_controller.rb +8 -0
- data/spec/{app/lib/assets → controll_app/app/models}/.gitkeep +0 -0
- data/spec/{app → controll_app}/app/models/post.rb +0 -0
- data/spec/{app → controll_app}/app/views/layouts/application.html.erb +0 -0
- data/spec/{app → controll_app}/app/views/posts/_form.html.erb +0 -0
- data/spec/{app → controll_app}/app/views/posts/edit.html.erb +0 -0
- data/spec/{app → controll_app}/app/views/posts/index.html.erb +0 -0
- data/spec/{app → controll_app}/app/views/posts/new.html.erb +0 -0
- data/spec/{app → controll_app}/app/views/posts/show.html.erb +0 -0
- data/spec/{app → controll_app}/config/application.rb +1 -1
- data/spec/{app → controll_app}/config/boot.rb +0 -0
- data/spec/{app → controll_app}/config/environment.rb +0 -0
- data/spec/{app → controll_app}/config/environments/development.rb +0 -0
- data/spec/{app → controll_app}/config/environments/test.rb +0 -0
- data/spec/{app → controll_app}/config/initializers/backtrace_silencers.rb +0 -0
- data/spec/{app → controll_app}/config/initializers/inflections.rb +0 -0
- data/spec/{app → controll_app}/config/initializers/mime_types.rb +0 -0
- data/spec/{app → controll_app}/config/initializers/secret_token.rb +0 -0
- data/spec/{app → controll_app}/config/initializers/session_store.rb +0 -0
- data/spec/{app → controll_app}/config/locales/en.yml +0 -0
- data/spec/controll_app/config/routes.rb +5 -0
- data/spec/{app → controll_app}/config.ru +0 -0
- data/spec/{app → controll_app}/db/seeds.rb +0 -0
- data/spec/{app/lib/tasks → controll_app/log}/.gitkeep +0 -0
- data/spec/{app → controll_app}/public/404.html +0 -0
- data/spec/{app → controll_app}/public/422.html +0 -0
- data/spec/{app → controll_app}/public/500.html +0 -0
- data/spec/{app → controll_app}/public/favicon.ico +0 -0
- data/spec/{app → controll_app}/public/index.html +0 -0
- data/spec/{app → controll_app}/public/javascripts/application.js +0 -0
- data/spec/{app → controll_app}/public/robots.txt +0 -0
- data/spec/{app → controll_app}/public/stylesheets/application.css +0 -0
- metadata +122 -85
- data/lib/controll/executor/notificator.rb +0 -12
- data/lib/controll/flow_handler/base.rb +0 -19
- data/lib/controll/flow_handler/control.rb +0 -85
- data/lib/controll/flow_handler/errors.rb +0 -5
- data/lib/controll/flow_handler/event_helper.rb +0 -18
- data/lib/controll/flow_handler/redirect/action.rb +0 -45
- data/lib/controll/flow_handler/redirect/mapper.rb +0 -41
- data/lib/controll/flow_handler/redirect.rb +0 -51
- data/lib/controll/flow_handler/render.rb +0 -51
- data/lib/controll/flow_handler.rb +0 -11
- data/lib/controll/helper/notify.rb +0 -74
- data/lib/controll/helper/path_resolver.rb +0 -45
- data/spec/app/app/controllers/posts_controller.rb +0 -52
- data/spec/app/config/routes.rb +0 -62
- data/spec/app/log/.gitkeep +0 -0
- data/spec/app/script/rails +0 -6
- data/spec/app/spec/controllers/posts_controller_spec.rb +0 -59
- data/spec/app/spec/isolated_spec_helper.rb +0 -6
- data/spec/app/spec/spec_helper.rb +0 -5
- data/spec/app/spec/unit/controllers/posts_controller_isolated_spec.rb +0 -63
- data/spec/app/spec/unit/controllers/posts_controller_spec.rb +0 -59
- data/spec/app/test/functional/.gitkeep +0 -0
- data/spec/app/test/functional/posts_controller_test.rb +0 -67
- data/spec/app/test/isolated_test_helper.rb +0 -7
- data/spec/app/test/test_helper.rb +0 -6
- data/spec/app/test/unit/.gitkeep +0 -0
- data/spec/app/test/unit/controllers/posts_controller_isolated_test.rb +0 -71
- data/spec/app/test/unit/controllers/posts_controller_test.rb +0 -67
- data/spec/app/vendor/assets/javascripts/.gitkeep +0 -0
- data/spec/app/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/app/vendor/plugins/.gitkeep +0 -0
- data/spec/controll/asssistant_spec.rb +0 -5
- data/spec/controll/flow_handler/control_spec.rb +0 -159
- data/spec/controll/flow_handler/redirect_spec.rb +0 -93
- data/spec/controll/helper/path_resolver_spec.rb +0 -49
- data/spec/controll/helper_spec.rb +0 -108
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
module Controll
|
|
2
|
-
class
|
|
1
|
+
module Controll
|
|
2
|
+
class Event::Matcher
|
|
3
3
|
attr_reader :event
|
|
4
4
|
|
|
5
5
|
def initialize event
|
|
@@ -12,7 +12,7 @@ module Controll::Helper
|
|
|
12
12
|
|
|
13
13
|
protected
|
|
14
14
|
|
|
15
|
-
include Controll::
|
|
15
|
+
include Controll::Event::Helper
|
|
16
16
|
|
|
17
17
|
def normalized events
|
|
18
18
|
[events].flatten.map(&:to_sym)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Controll
|
|
2
|
+
class Event
|
|
3
|
+
autoload :Helper, 'controll/event/helper'
|
|
4
|
+
autoload :Matcher, 'controll/event/matcher'
|
|
5
|
+
|
|
6
|
+
class InvalidError < StandardError; end
|
|
7
|
+
|
|
8
|
+
attr_reader :name, :type, :options
|
|
9
|
+
|
|
10
|
+
def initialize name, *args
|
|
11
|
+
raise ArgumentError, "Event must have a name identifier" if name.blank?
|
|
12
|
+
@name = name.to_sym
|
|
13
|
+
@options = args.extract_options!
|
|
14
|
+
@type = (extract_type(args.first) || options[:type] || :notice).to_sym
|
|
15
|
+
raise ArgumentError, "Invalid type: #{@type} must be one of: #{self.class.valid_types}" unless self.class.valid_type? @type
|
|
16
|
+
@options.delete(:type) if options[:type] == @type
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.default_valid_types
|
|
20
|
+
[:notice, :error, :warning, :success]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.valid_types
|
|
24
|
+
@valid_types ||= default_valid_types
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.reset_types
|
|
28
|
+
@valid_types = default_valid_types
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
valid_types.each do |type|
|
|
32
|
+
define_method :"#{type}?" do
|
|
33
|
+
self.type == type.to_sym
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class << self
|
|
38
|
+
attr_writer :valid_types
|
|
39
|
+
|
|
40
|
+
def valid_type? type
|
|
41
|
+
valid_types.map(&:to_sym).include? type.to_sym
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_valid_types *types
|
|
45
|
+
@valid_types += types if types.all? {|type| type.kind_of? Symbol}
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
protected
|
|
50
|
+
|
|
51
|
+
def extract_type arg
|
|
52
|
+
return arg.type if arg.respond_to? :type
|
|
53
|
+
arg.to_sym if type? arg
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def type? arg
|
|
57
|
+
arg.kind_of?(String) || arg.kind_of?(Symbol)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Controll
|
|
2
|
+
class Events
|
|
3
|
+
include Enumerable
|
|
4
|
+
include Controll::Event::Helper
|
|
5
|
+
|
|
6
|
+
attr_reader :events
|
|
7
|
+
|
|
8
|
+
def initialize *events
|
|
9
|
+
@events = events.flatten.map{|event| normalize event }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def each
|
|
13
|
+
events.each {|event| yield event }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def << event
|
|
17
|
+
events << event
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def last
|
|
21
|
+
events.last
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.valid_types
|
|
25
|
+
Controll::Event.valid_types
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# fx error? - returns if any event of type error
|
|
29
|
+
valid_types.each do |type|
|
|
30
|
+
meth = :"#{type}?"
|
|
31
|
+
define_method meth do
|
|
32
|
+
self.any? {|event| event.send(meth) }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# fx errors - returns all events of type error
|
|
37
|
+
valid_types.each do |type|
|
|
38
|
+
meth = type.to_s.pluralize
|
|
39
|
+
define_method meth do
|
|
40
|
+
self.select {|event| event.send(:"#{type}?") }
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def valid_types
|
|
45
|
+
Controll::Event.valid_types
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
module Controll
|
|
2
2
|
module Executor
|
|
3
3
|
class Base
|
|
4
|
-
attr_accessor :
|
|
4
|
+
attr_accessor :controller, :options
|
|
5
5
|
|
|
6
|
-
def initialize
|
|
7
|
-
@
|
|
6
|
+
def initialize controller, options = {}
|
|
7
|
+
@controller = controller
|
|
8
8
|
@options = options
|
|
9
9
|
end
|
|
10
|
-
|
|
11
|
-
def method_missing(meth, *args, &block)
|
|
12
|
-
initiator.send(meth, *args, &block)
|
|
13
|
-
end
|
|
14
10
|
end
|
|
15
11
|
end
|
|
16
12
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'controll/executor/base'
|
|
2
|
+
|
|
3
|
+
module Controll::Executor
|
|
4
|
+
class Controlled < Delegator
|
|
5
|
+
|
|
6
|
+
def execute
|
|
7
|
+
validations
|
|
8
|
+
do_command unless error?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# return last notification or :success as result
|
|
12
|
+
# return <Event>
|
|
13
|
+
def result
|
|
14
|
+
main_event
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
def execute &block
|
|
19
|
+
define_method :execute do
|
|
20
|
+
super
|
|
21
|
+
instance_eval &block
|
|
22
|
+
result
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
protected
|
|
28
|
+
|
|
29
|
+
def validations
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def error?
|
|
33
|
+
notifications.error?
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/controll/executor.rb
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
module Controll
|
|
2
2
|
module Executor
|
|
3
3
|
autoload :Base, 'controll/executor/base'
|
|
4
|
-
autoload :
|
|
4
|
+
autoload :Controlled, 'controll/executor/controlled'
|
|
5
|
+
autoload :Delegator, 'controll/executor/delegator'
|
|
5
6
|
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module Executors
|
|
10
|
+
Base = Controll::Executor::Base
|
|
11
|
+
Delegator = Controll::Executor::Delegator
|
|
12
|
+
Controlled = Controll::Executor::Controlled
|
|
6
13
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Controll::Flow::Action
|
|
2
|
+
class Base
|
|
3
|
+
attr_reader :path, :controller, :errors
|
|
4
|
+
|
|
5
|
+
def initialize controller, path
|
|
6
|
+
@controller = controller
|
|
7
|
+
@path = path.to_s
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def set_errors *errors
|
|
11
|
+
@errors = errors.flatten
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def errors
|
|
15
|
+
@errors |= []
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
protected
|
|
19
|
+
|
|
20
|
+
def controller_action
|
|
21
|
+
@controller_action ||= "do_#{type}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def error_check!
|
|
25
|
+
unless controller.respond_to? controller_action
|
|
26
|
+
raise Controll::NotEnabled, "Controll::Enabler has not been included in #{controller.class}. Missing #{controller_action} method"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Controll::Flow::Action
|
|
2
|
+
class Fallback < Base
|
|
3
|
+
attr_reader :controller, :event
|
|
4
|
+
|
|
5
|
+
def initialize controller, event = nil
|
|
6
|
+
@controller = controller
|
|
7
|
+
@event = event if event
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def perform
|
|
11
|
+
error_check! if event
|
|
12
|
+
controller.do_fallback self
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def type
|
|
16
|
+
:fallback
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class << self
|
|
20
|
+
def action controller, event = nil
|
|
21
|
+
self.new controller, event
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Controll::Flow::Action
|
|
2
|
+
class PathAction < Base
|
|
3
|
+
def perform
|
|
4
|
+
raise BadPathError, "Bad path: #{path}" if path.blank?
|
|
5
|
+
error_check!
|
|
6
|
+
controller.send controller_action, self
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def resolved_path
|
|
10
|
+
controller.send(path)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
protected
|
|
14
|
+
|
|
15
|
+
# useful for path helpers used in event maps
|
|
16
|
+
def method_missing(method_name, *args, &block)
|
|
17
|
+
if controller.respond_to? method_name
|
|
18
|
+
controller.send method_name, *args, &block
|
|
19
|
+
else
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module Controll::Flow::ActionMapper
|
|
2
|
+
class Base
|
|
3
|
+
class << self
|
|
4
|
+
def path_action_class
|
|
5
|
+
Controll::Flow::Action::PathAction
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def action controller, event
|
|
9
|
+
raise NotImplementedError, 'You must implement the #action class method'
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Controll::Flow::ActionMapper
|
|
2
|
+
class Complex < Base
|
|
3
|
+
attr_reader :event_maps
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
attr_writer :action_clazz
|
|
7
|
+
attr_reader :types, :event_maps
|
|
8
|
+
|
|
9
|
+
# this method could be generated whenever a class inherits from ActionHandler class?
|
|
10
|
+
def inherited base
|
|
11
|
+
if base.parent.respond_to? :add_action_handler
|
|
12
|
+
base.add_action_handler self.name.demodulize
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def action controller, event
|
|
17
|
+
action_types ||= types
|
|
18
|
+
path = path_finder(event).path
|
|
19
|
+
path_action_class.new controller, path unless path.blank?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# reader
|
|
23
|
+
def event_map_for type = :notice
|
|
24
|
+
@event_maps ||= {}
|
|
25
|
+
event_maps[type.to_sym] || {}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# writer
|
|
29
|
+
# also auto-adds type to types
|
|
30
|
+
def event_map *args, &block
|
|
31
|
+
@event_maps ||= {}
|
|
32
|
+
@types ||= []
|
|
33
|
+
return @event_maps if args.empty? && !block_given?
|
|
34
|
+
|
|
35
|
+
type = args.first.kind_of?(Symbol) ? args.shift : :notice
|
|
36
|
+
event_maps[type.to_sym] = block_given? ? instance_eval(&block) : args.first
|
|
37
|
+
@types << type unless types.include?(type)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
protected
|
|
41
|
+
|
|
42
|
+
def path_finder event
|
|
43
|
+
raise Controll::Flow::NoMappingFoundError, "No event maps defined" if event_maps.blank?
|
|
44
|
+
path_finder_class.new event, event_maps, types
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def path_finder_class
|
|
48
|
+
Controll::Flow::EventMapper::PathFinder
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Controll::Flow::ActionMapper
|
|
2
|
+
class Simple < Base
|
|
3
|
+
NoEventsDefinedError = Controll::Flow::NoEventsDefinedError
|
|
4
|
+
NoDefaultPathDefinedError = Controll::Flow::NoDefaultPathDefinedError
|
|
5
|
+
|
|
6
|
+
# TODO: Should combine with Redirecter style, allowing for multiple render path mappings!
|
|
7
|
+
# This is fx useful for Wizards etc. where one Controller can render to many views, depending on state
|
|
8
|
+
class << self
|
|
9
|
+
def inherited base
|
|
10
|
+
if base.parent.respond_to? :add_action_handler
|
|
11
|
+
base.add_action_handler self.name.demodulize
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def action controller, event, path = nil
|
|
16
|
+
check!
|
|
17
|
+
event = normalize event
|
|
18
|
+
path_action_class.new(controller, path || default_path) if events.include? event.name
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# http://bugs.ruby-lang.org/issues/1082
|
|
22
|
+
# hello.singleton_class
|
|
23
|
+
# Instead of always having to write:
|
|
24
|
+
# (class << hello; self; end)
|
|
25
|
+
def default_path str = nil, &block
|
|
26
|
+
(class << self; self; end).send :define_method, :default_path do
|
|
27
|
+
block_given? ? instance_eval(&block) : str
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def events *args, &block
|
|
32
|
+
(class << self; self; end).send :define_method, :events do
|
|
33
|
+
args.flatten
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
default_path(&block) if block_given?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
protected
|
|
40
|
+
|
|
41
|
+
def check!
|
|
42
|
+
unless respond_to?(:events) && !events.blank?
|
|
43
|
+
raise NoEventsDefinedError, "You must define the events/actions that can be mapped by this class"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
unless respond_to?(:default_path) && !default_path.blank?
|
|
47
|
+
raise NoDefaultPathDefinedError, "You must set a default_path to be routed to if no event/action matches"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
include Controll::Event::Helper
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Controll::Flow
|
|
2
|
+
class ActionEventError < StandardError; end
|
|
3
|
+
|
|
4
|
+
class EventNotImplementedError < StandardError; end
|
|
5
|
+
|
|
6
|
+
class PathActionError < StandardError; end
|
|
7
|
+
|
|
8
|
+
# Complex mapper
|
|
9
|
+
class NoMappingFoundError < PathActionError; end
|
|
10
|
+
|
|
11
|
+
# Simple mapper
|
|
12
|
+
class NoEventsDefinedError < PathActionError; end
|
|
13
|
+
class NoDefaultPathDefinedError < PathActionError; end
|
|
14
|
+
|
|
15
|
+
class BadPathError < PathActionError; end
|
|
16
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Controll::Flow
|
|
2
|
+
module EventMapper
|
|
3
|
+
class PathFinder
|
|
4
|
+
attr_accessor :event, :maps, :types
|
|
5
|
+
|
|
6
|
+
NoMappingFoundError = Controll::Flow::NoMappingFoundError
|
|
7
|
+
|
|
8
|
+
# event <Event>
|
|
9
|
+
def initialize event, maps, types = []
|
|
10
|
+
raise ArgumentError, "Event argument must not be empty" if event.blank?
|
|
11
|
+
raise ArgumentError, "Maps argument must not be empty" if maps.blank?
|
|
12
|
+
@event = normalize event
|
|
13
|
+
@types = types unless types.blank?
|
|
14
|
+
@maps = maps
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def path
|
|
18
|
+
@path ||= mapper.map_event
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
raise NoMappingFoundError, "No event mapping could be found for: #{event.inspect} in: #{maps}. Cause: #{e}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
protected
|
|
24
|
+
|
|
25
|
+
include Controll::Event::Helper
|
|
26
|
+
|
|
27
|
+
def event_map
|
|
28
|
+
@event_map ||= maps[event.type] || {}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def mapper
|
|
32
|
+
@mapper ||= Controll::Flow::EventMapper::Util.new event, event_map
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Controll::Flow
|
|
2
|
+
module EventMapper
|
|
3
|
+
class Util
|
|
4
|
+
attr_reader :event_map, :event
|
|
5
|
+
|
|
6
|
+
NoMappingFoundError = Controll::Flow::NoMappingFoundError
|
|
7
|
+
|
|
8
|
+
def initialize event, event_map
|
|
9
|
+
@event ||= normalize event
|
|
10
|
+
|
|
11
|
+
unless valid_map? event_map
|
|
12
|
+
raise ArgumentError, "Invalid redirect map: #{event_map}, must be a non-empty Hash"
|
|
13
|
+
end
|
|
14
|
+
@event_map ||= event_map
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# An event can also be a Symbol,
|
|
18
|
+
# in which case it is a :notice event
|
|
19
|
+
def map_event
|
|
20
|
+
event_map.each do |path, events|
|
|
21
|
+
return path.to_s if valid? events
|
|
22
|
+
end
|
|
23
|
+
raise NoMappingFoundError, "No path could be found for event: #{event.inspect} in map: #{event_map}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
protected
|
|
27
|
+
|
|
28
|
+
include Controll::Event::Helper
|
|
29
|
+
|
|
30
|
+
def valid_map? event_map
|
|
31
|
+
event_map.kind_of?(Hash) && !event_map.blank?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def valid? events
|
|
35
|
+
matcher.match?(events)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def matcher
|
|
39
|
+
@matcher ||= Controll::Event::Matcher.new event
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Controll::Flow
|
|
2
|
+
class Master
|
|
3
|
+
class Executor < Controll::Executor::Base
|
|
4
|
+
Flow = Controll::Flow
|
|
5
|
+
|
|
6
|
+
NoEventsDefinedError = Flow::NoEventsDefinedError
|
|
7
|
+
NoMappingFoundError = Flow::NoMappingFoundError
|
|
8
|
+
|
|
9
|
+
attr_reader :event, :action_handlers
|
|
10
|
+
|
|
11
|
+
def initialize initiator, options
|
|
12
|
+
raise ArgumentError, "Must take an options arg" unless options.kind_of?(Hash)
|
|
13
|
+
raise ArgumentError, "Must take an :event option" unless options[:event]
|
|
14
|
+
raise ArgumentError, "Must take an :action_handlers option" unless options[:action_handlers]
|
|
15
|
+
super
|
|
16
|
+
@event = options[:event]
|
|
17
|
+
@action_handlers = options[:action_handlers]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def execute
|
|
21
|
+
action_handlers.each do |action_handler|
|
|
22
|
+
begin
|
|
23
|
+
action_handler_clazz = handler_class(action_handler)
|
|
24
|
+
next unless action_handler_clazz
|
|
25
|
+
return action_handler_clazz.action(controller, event)
|
|
26
|
+
rescue NoEventsDefinedError => e
|
|
27
|
+
errors << e
|
|
28
|
+
rescue NoMappingFoundError => e
|
|
29
|
+
errors << e
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
fallback
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def errors
|
|
36
|
+
@errors ||= []
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
protected
|
|
40
|
+
|
|
41
|
+
def fallback
|
|
42
|
+
fallback_class.new controller, event
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def fallback_class
|
|
46
|
+
Flow::Action::Fallback
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def handler_class action_handler
|
|
50
|
+
clazz = "#{initiator.class}::#{action_handler.to_s.camelize}"
|
|
51
|
+
clazz.constantize
|
|
52
|
+
rescue NameError
|
|
53
|
+
nil
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Controll::Flow
|
|
2
|
+
class Master
|
|
3
|
+
module Macros
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
module ClassMethods
|
|
7
|
+
def handler options = {}, &block
|
|
8
|
+
mapper_type = :simple if options[:simple]
|
|
9
|
+
mapper_type ||= :complex if options[:complex]
|
|
10
|
+
|
|
11
|
+
master_clazz = Controll::Flow::Master
|
|
12
|
+
|
|
13
|
+
unless mapper_type
|
|
14
|
+
raise ArgumentError, "You must specify mapper type, one of: #{master_clazz.mapper_types} in: #{options}"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
handler_type = options.delete(mapper_type)
|
|
18
|
+
|
|
19
|
+
unless master_clazz.valid_handler? handler_type
|
|
20
|
+
raise ArgumentError, "Must one of: #{master_clazz.valid_handlers} was: #{handler_type}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
parent = "Controll::Flow::ActionMapper::#{mapper_type.to_s.camelize}".constantize
|
|
24
|
+
|
|
25
|
+
clazz_name = handler_type.to_s.camelize
|
|
26
|
+
context = self.kind_of?(Class) ? self : self.class
|
|
27
|
+
|
|
28
|
+
clazz = parent ? Class.new(parent) : Class.new
|
|
29
|
+
context.const_set clazz_name, clazz
|
|
30
|
+
clazz = context.const_get(clazz_name)
|
|
31
|
+
|
|
32
|
+
container_class_name = clazz.name.sub(/\.*(::\w+)$/, '')
|
|
33
|
+
container_class = container_class_name.constantize
|
|
34
|
+
container_class.add_action_handler clazz.name.demodulize
|
|
35
|
+
|
|
36
|
+
clazz.instance_eval(&block) if block_given?
|
|
37
|
+
clazz
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def renderer mapper_type = :simple, options = {}, &block
|
|
41
|
+
handler options.merge(mapper_type => :renderer), &block
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def redirecter mapper_type = :complex, options = {}, &block
|
|
45
|
+
handler options.merge(mapper_type => :redirecter), &block
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def event &block
|
|
49
|
+
raise ArgumentError, "Must be called with a block" unless block_given?
|
|
50
|
+
define_method :event do
|
|
51
|
+
instance_variable_get("@event") || instance_variable_set("@event", instance_eval(&block))
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# def set_action_handlers *names, &block
|
|
56
|
+
# raise ArgumentError, "Must be called with names of action handlers" if names.empty?
|
|
57
|
+
|
|
58
|
+
# define_method :action_handlers do
|
|
59
|
+
# value = block_given? ? instance_eval(&block) : names.flatten
|
|
60
|
+
# instance_variable_get("@action_handlers") || instance_variable_set("@action_handlers", value)
|
|
61
|
+
# end
|
|
62
|
+
# end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|