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
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module Controll::Flow
|
|
2
|
+
class Master
|
|
3
|
+
autoload :Macros, 'controll/flow/master/macros'
|
|
4
|
+
autoload :Executor, 'controll/flow/master/executor'
|
|
5
|
+
|
|
6
|
+
include Macros
|
|
7
|
+
|
|
8
|
+
attr_reader :controller, :action, :options
|
|
9
|
+
|
|
10
|
+
def initialize controller, options = {}
|
|
11
|
+
@controller = controller
|
|
12
|
+
@options = options
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Uses Executor to execute each registered ActionHandler, such ad Renderer and Redirecter
|
|
16
|
+
# The first ActionHandler matching the event returns an appropriate Action
|
|
17
|
+
# In case no ActionHandler matches, the Fallback action is returned
|
|
18
|
+
def execute
|
|
19
|
+
@action = executor.execute || fallback
|
|
20
|
+
@action.set_errors errors
|
|
21
|
+
@action
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def executor
|
|
25
|
+
@executor ||= Executor.new controller, executor_options
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def executor_options
|
|
29
|
+
{event: event, action_handlers: action_handlers}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
delegate :errors, to: :executor
|
|
33
|
+
|
|
34
|
+
class << self
|
|
35
|
+
def action_handlers
|
|
36
|
+
@action_handlers ||= []
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def add_action_handler name
|
|
40
|
+
@action_handlers ||= []
|
|
41
|
+
@action_handlers << name.to_s.underscore.to_sym
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def valid_handler? handler_type
|
|
45
|
+
raise ArgumentError, "Must be a String or Symbol, was: #{handler_type}" if handler_type.blank?
|
|
46
|
+
valid_handlers.include? handler_type.to_sym
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def valid_handlers
|
|
50
|
+
[:renderer, :redirecter]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def mapper_types
|
|
54
|
+
[:simple, :complex]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
protected
|
|
59
|
+
|
|
60
|
+
delegate :command!, to: :controller
|
|
61
|
+
|
|
62
|
+
def action_handlers
|
|
63
|
+
self.class.action_handlers
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def event
|
|
67
|
+
raise Controll::Flow::EventNotImplementedError, 'You must define an #event method that returns an event (or Symbol). You can use an Executor for this.'
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'controll/flow/errors'
|
|
2
|
+
|
|
3
|
+
module Controll
|
|
4
|
+
module Flow
|
|
5
|
+
autoload :Master, 'controll/flow/master'
|
|
6
|
+
autoload :Action, 'controll/flow/action'
|
|
7
|
+
autoload :EventMapper, 'controll/flow/event_mapper'
|
|
8
|
+
autoload :ActionMapper, 'controll/flow/action_mapper'
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module Flows
|
|
13
|
+
Master = Controll::Flow::Master
|
|
14
|
+
Flow = Controll::Flow::Master
|
|
15
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Controll
|
|
2
|
+
module Focused
|
|
3
|
+
module Enabler
|
|
4
|
+
include Controll::Enabler
|
|
5
|
+
|
|
6
|
+
def execute
|
|
7
|
+
action.perform
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.assistant_methods *names
|
|
11
|
+
delegate names, to: :assistant
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
protected
|
|
15
|
+
|
|
16
|
+
# the action resulting from executing the flow.
|
|
17
|
+
# Should be an instance of either:
|
|
18
|
+
# - Fallback
|
|
19
|
+
# - Redirecter
|
|
20
|
+
# - Renderer
|
|
21
|
+
def action
|
|
22
|
+
@action ||= flow.execute
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @flowhandler ||= Controll::Flow::Master.new self
|
|
26
|
+
def flow
|
|
27
|
+
raise NotImplementedError, '#flow must return the Controll::Flow::Master instance to be used'
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/controll/helper.rb
CHANGED
|
@@ -1,101 +1,7 @@
|
|
|
1
1
|
module Controll
|
|
2
2
|
module Helper
|
|
3
|
-
autoload :Notify, 'controll/helper/notify'
|
|
4
3
|
autoload :HashAccess, 'controll/helper/hash_access'
|
|
5
4
|
autoload :Params, 'controll/helper/params'
|
|
6
5
|
autoload :Session, 'controll/helper/session'
|
|
7
|
-
autoload :PathResolver, 'controll/helper/path_resolver'
|
|
8
|
-
autoload :EventMatcher, 'controll/helper/event_matcher'
|
|
9
|
-
|
|
10
|
-
include Controll::Helper::Notify
|
|
11
|
-
include Controll::Helper::Params
|
|
12
|
-
|
|
13
|
-
extend ActiveSupport::Concern
|
|
14
|
-
|
|
15
|
-
delegate :command, :command!, :use_command, to: :commander
|
|
16
|
-
|
|
17
|
-
module ClassMethods
|
|
18
|
-
# TODO: refactor - all use exactly the same pattern - can be generated!
|
|
19
|
-
def commander name, options = {}
|
|
20
|
-
define_method :commander do
|
|
21
|
-
unless instance_variable_get("@commander")
|
|
22
|
-
clazz = "#{name.to_s.camelize}Commander".constantize
|
|
23
|
-
instance_variable_set "@commander", clazz.new(self, options)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def message_handler name, options = {}
|
|
29
|
-
define_method :message_handler do
|
|
30
|
-
unless instance_variable_get("@message_handler")
|
|
31
|
-
clazz = "#{name.to_s.camelize}MessageHandler".constantize
|
|
32
|
-
instance_variable_set "@message_handler", clazz.new(self, options)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def assistant name, options = {}
|
|
38
|
-
define_method :assistant do
|
|
39
|
-
unless instance_variable_get("@assistant")
|
|
40
|
-
clazz = "#{name.to_s.camelize}Assistant".constantize
|
|
41
|
-
instance_variable_set "@assistant", clazz.new(self, options)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def flow_handler name, options = {}
|
|
47
|
-
define_method :flow_handler do
|
|
48
|
-
unless instance_variable_get("@flow_handler")
|
|
49
|
-
clazz = "#{name.to_s.camelize}FlowHandler".constantize
|
|
50
|
-
instance_variable_set "@flow_handler", clazz.new(self, options)
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def delegate_assistant name, options = {}
|
|
56
|
-
define_method :assistant do
|
|
57
|
-
unless instance_variable_get("@assistant")
|
|
58
|
-
clazz = "#{name.to_s.camelize}DelegateAssistant".constantize
|
|
59
|
-
instance_variable_set "@assistant", clazz.new(self, options)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def redirect_map map = {}
|
|
65
|
-
@redirect_map ||= map
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def render_map map = {}
|
|
69
|
-
@render_map ||= map
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def do_redirect *args
|
|
74
|
-
options = args.extract_options!
|
|
75
|
-
path = path_resolver.extract_path(:redirect_map, *args)
|
|
76
|
-
process_notifications
|
|
77
|
-
redirect_to path, *args
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def do_render *args
|
|
81
|
-
options = args.extract_options!
|
|
82
|
-
path = path_resolver.extract_path :render_paths, *args
|
|
83
|
-
process_notifications
|
|
84
|
-
render path, *args
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
protected
|
|
88
|
-
|
|
89
|
-
def redirect_map
|
|
90
|
-
self.class.redirect_map
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def render_paths
|
|
94
|
-
self.class.render_map
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def path_resolver
|
|
98
|
-
@path_resolver ||= PathResolver.new self
|
|
99
|
-
end
|
|
100
6
|
end
|
|
101
7
|
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Controll
|
|
2
|
+
module Macros
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def enable_controll
|
|
7
|
+
clazz = self.ancestors.include?(::Imperator::Command) ? Controll::Focused::Enabler : Controll::Enabler
|
|
8
|
+
self.send :include, clazz
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
data/lib/controll/notify/base.rb
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
require 'liquid'
|
|
2
1
|
require 'controll/notify/flash'
|
|
3
2
|
|
|
4
3
|
module Controll
|
|
5
4
|
module Notify
|
|
6
5
|
class Base < Flash
|
|
7
|
-
|
|
6
|
+
Message = Controll::Notify::Message
|
|
7
|
+
|
|
8
|
+
attr_reader :name
|
|
8
9
|
|
|
9
10
|
def notify name, options = {}
|
|
10
|
-
@options.merge! options
|
|
11
|
-
|
|
11
|
+
@options.merge! options
|
|
12
|
+
@name = name
|
|
13
|
+
signal message_resolver.resolve
|
|
12
14
|
end
|
|
13
15
|
|
|
14
16
|
def self.inherited(base)
|
|
@@ -16,7 +18,9 @@ module Controll
|
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
module ClassMethods
|
|
19
|
-
|
|
21
|
+
def signal_type
|
|
22
|
+
@signal_type ||= self.name.demodulize.sub(/Handler$/, '').underscore.to_sym
|
|
23
|
+
end
|
|
20
24
|
|
|
21
25
|
def type name
|
|
22
26
|
@signal_type = name
|
|
@@ -25,51 +29,26 @@ module Controll
|
|
|
25
29
|
|
|
26
30
|
protected
|
|
27
31
|
|
|
28
|
-
def
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
msg = send(name) if respond_to? name
|
|
32
|
-
msg ||= messages[name.to_sym] if respond_to? :messages
|
|
33
|
-
msg ||= name.to_sym
|
|
34
|
-
|
|
35
|
-
# if name is not mapped to a message, it could well be, that the
|
|
36
|
-
# event should not generate a nofification message
|
|
37
|
-
return nil if !msg
|
|
38
|
-
|
|
39
|
-
# try various approaches!
|
|
40
|
-
case msg
|
|
41
|
-
when Symbol
|
|
42
|
-
translate msg, opts
|
|
43
|
-
when String
|
|
44
|
-
msg.strip!
|
|
45
|
-
return replace_args(msg, opts) if msg =~ /{{.*}}/
|
|
46
|
-
msg
|
|
47
|
-
else
|
|
48
|
-
msg_error!
|
|
49
|
-
end
|
|
50
|
-
rescue
|
|
32
|
+
def message_resolver
|
|
33
|
+
@message_resolver ||= Message::Resolver.new self, message
|
|
51
34
|
end
|
|
52
35
|
|
|
53
|
-
def
|
|
54
|
-
|
|
55
|
-
end
|
|
36
|
+
def message
|
|
37
|
+
@message ||= Message.new text, options
|
|
38
|
+
end
|
|
56
39
|
|
|
57
|
-
def
|
|
58
|
-
|
|
40
|
+
def text
|
|
41
|
+
@text ||= resolve_text(name) || key
|
|
59
42
|
end
|
|
60
43
|
|
|
61
|
-
def
|
|
62
|
-
|
|
63
|
-
Liquid::Template.parse(msg).render(opts)
|
|
44
|
+
def key
|
|
45
|
+
@key ||= name.to_sym
|
|
64
46
|
end
|
|
65
47
|
|
|
66
|
-
def
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
ns = [middle, type].join('.').sub /^./, ''
|
|
71
|
-
[ns,msg].join('.')
|
|
72
|
-
end
|
|
48
|
+
def resolve_text name
|
|
49
|
+
return send(name) if respond_to? name
|
|
50
|
+
messages[name.to_sym] if respond_to? :messages
|
|
51
|
+
end
|
|
73
52
|
end
|
|
74
53
|
end
|
|
75
54
|
end
|
|
@@ -20,11 +20,11 @@ module Controll
|
|
|
20
20
|
attr_writer :types
|
|
21
21
|
|
|
22
22
|
def types
|
|
23
|
-
@types ||=
|
|
23
|
+
@types ||= Controll::Event.valid_types
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def add_types *types
|
|
27
|
-
@types += types.
|
|
27
|
+
@types += types if types.all? {|type| type.kind_of? Symbol}
|
|
28
28
|
end
|
|
29
29
|
alias_method :add_type, :add_types
|
|
30
30
|
end
|
|
@@ -41,7 +41,7 @@ module Controll
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def types
|
|
44
|
-
self.class.types
|
|
44
|
+
self.class.types.map(&:to_sym)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def signal_type
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Controll::Notify
|
|
2
|
+
module Macros
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def handler type, options = {}, &block
|
|
7
|
+
unless valid_type? type
|
|
8
|
+
raise ArgumentError, "Notification type must be any of: #{types}, was: #{type}"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
clazz_name = "#{parent}::#{type.to_s.camelize}Handler"
|
|
12
|
+
parent = options[:parent] || Controll::Notify::Base
|
|
13
|
+
|
|
14
|
+
clazz = parent ? Class.new(parent) : Class.new
|
|
15
|
+
Object.const_set clazz_name, clazz
|
|
16
|
+
context = self.kind_of?(Class) ? self : self.class
|
|
17
|
+
clazz = context.const_get(clazz_name)
|
|
18
|
+
|
|
19
|
+
if block_given?
|
|
20
|
+
clazz.instance_eval &block
|
|
21
|
+
end
|
|
22
|
+
clazz
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def messages hash = nil, &block
|
|
26
|
+
unless block_given? || !hash.blank?
|
|
27
|
+
raise ArgumentError, "Must be called with non-empty Hash or block"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
define_method :messages do
|
|
31
|
+
block_given? ? instance_eval(&block) : hash
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def message event_name, text = nil, &block
|
|
36
|
+
unless event_name.kind_of?(Symbol) || event_name.kind_of?(String)
|
|
37
|
+
raise ArgumentError, "First argument must be an event name, was: #{event_name}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
unless block_given? || !text.blank?
|
|
41
|
+
raise ArgumentError, "Must be called with non-empty String or block"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
define_method event_name do
|
|
45
|
+
block_given? ? instance_eval(&block) : hash
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
alias_method :msg, :message
|
|
49
|
+
|
|
50
|
+
protected
|
|
51
|
+
|
|
52
|
+
def valid_type? type
|
|
53
|
+
types.include? type.to_sym
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'liquid'
|
|
2
|
+
|
|
3
|
+
module Controll::Notify
|
|
4
|
+
class Message
|
|
5
|
+
class Handler
|
|
6
|
+
attr_reader :message
|
|
7
|
+
|
|
8
|
+
def initialize message
|
|
9
|
+
@message = message
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def handle
|
|
13
|
+
return args? ? replace_args : message.text
|
|
14
|
+
rescue StandardError
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
protected
|
|
19
|
+
|
|
20
|
+
delegate :text, to: :message
|
|
21
|
+
|
|
22
|
+
def options
|
|
23
|
+
@options ||= message.options.stringify_keys
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def args?
|
|
27
|
+
text =~ /{{.*}}/
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def replace_args
|
|
31
|
+
# Parses and compiles the template
|
|
32
|
+
Liquid::Template.parse(text).render(options)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Controll::Notify
|
|
2
|
+
class Message
|
|
3
|
+
class Resolver
|
|
4
|
+
Message = Controll::Notify::Message
|
|
5
|
+
|
|
6
|
+
attr_reader :caller, :message
|
|
7
|
+
|
|
8
|
+
def initialize caller, message
|
|
9
|
+
@caller = caller
|
|
10
|
+
@message = message
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def resolve
|
|
14
|
+
message.translate? ? translator.translate : message_handler.handle
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
protected
|
|
18
|
+
|
|
19
|
+
def message_handler
|
|
20
|
+
Message::Handler.new message
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def translator
|
|
24
|
+
Message::Translator.new caller, message
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Controll
|
|
2
|
+
module Notify
|
|
3
|
+
class Message
|
|
4
|
+
class Translator
|
|
5
|
+
attr_reader :caller, :key, :options
|
|
6
|
+
|
|
7
|
+
def initialize caller, message
|
|
8
|
+
@caller = caller
|
|
9
|
+
@key = message.text
|
|
10
|
+
@options = message.options.symbolize_keys
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def translate
|
|
14
|
+
I18n.t i18n_key, options
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
protected
|
|
18
|
+
|
|
19
|
+
def i18n_key
|
|
20
|
+
[namespace_key, key].join('.')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def namespace_key
|
|
24
|
+
[namespace, type].join('.').sub /^\\./, ''
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def parts
|
|
28
|
+
@parts ||= caller.class.name.split('::')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def namespace
|
|
32
|
+
(parts.first == 'Notifiers' ? parts[1..-2] : parts[0..-2]).join('.').underscore
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def type
|
|
36
|
+
parts.last.sub(/#{clazz_postfix}$/, '').underscore
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def clazz_postfix
|
|
40
|
+
'Handler'
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Controll::Notify
|
|
2
|
+
class Message
|
|
3
|
+
autoload :Translator, 'controll/notify/message/translator'
|
|
4
|
+
autoload :Handler, 'controll/notify/message/handler'
|
|
5
|
+
autoload :Resolver, 'controll/notify/message/resolver'
|
|
6
|
+
|
|
7
|
+
attr_reader :text, :options
|
|
8
|
+
|
|
9
|
+
def initialize text, options = {}
|
|
10
|
+
raise ArgumentError, "Message text must be a String or Symbol" unless valid_text? text
|
|
11
|
+
@text = text
|
|
12
|
+
@options = options
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def translate?
|
|
16
|
+
text.kind_of? Symbol
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
protected
|
|
20
|
+
|
|
21
|
+
def valid_text? text
|
|
22
|
+
text.kind_of?(String) || text.kind_of?(Symbol)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -3,36 +3,27 @@ require 'controll/notify/flash'
|
|
|
3
3
|
module Controll
|
|
4
4
|
module Notify
|
|
5
5
|
class Typed < Flash
|
|
6
|
-
class
|
|
6
|
+
class MissingNotifyHandlerClass < StandardError; end
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
raise MissingNotifyClass, "#{msg_class(:notice)} class missing" unless msg_class(:notice)
|
|
10
|
-
@notice ||= msg_class(:notice).new flash #, options
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def error
|
|
14
|
-
raise MissingNotifyClass, "#{msg_class(:warning)} class missing" unless msg_class(:error)
|
|
15
|
-
@error ||= msg_class(:error).new flash #, options
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def success
|
|
19
|
-
raise MissingNotifyClass, "#{msg_class(:success)} class missing" unless msg_class(:success)
|
|
20
|
-
@success ||= msg_class(:success).new flash #, options
|
|
21
|
-
end
|
|
8
|
+
include Controll::Notify::Macros
|
|
22
9
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
10
|
+
types.each do |type|
|
|
11
|
+
define_method type do
|
|
12
|
+
clazz = handler_class(type)
|
|
13
|
+
raise MissingNotifyHandlerClass, "#{clazz} class missing" unless clazz
|
|
14
|
+
var = "@#{type}"
|
|
15
|
+
instance_variable_get(var) || instance_variable_set(var, clazz.new(flash))
|
|
16
|
+
end
|
|
26
17
|
end
|
|
27
18
|
|
|
28
19
|
protected
|
|
29
20
|
|
|
30
|
-
def
|
|
31
|
-
|
|
21
|
+
def handler_class name
|
|
22
|
+
handler_classes[name] ||= "#{self.class}::#{name.to_s.camelize}Handler".constantize
|
|
32
23
|
end
|
|
33
24
|
|
|
34
|
-
def
|
|
35
|
-
@
|
|
25
|
+
def handler_classes
|
|
26
|
+
@handler_classes ||= {}
|
|
36
27
|
end
|
|
37
28
|
end
|
|
38
29
|
end
|
data/lib/controll/notify.rb
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
module Controll
|
|
2
2
|
module Notify
|
|
3
|
-
autoload :Base,
|
|
4
|
-
autoload :Flash,
|
|
5
|
-
autoload :Typed,
|
|
3
|
+
autoload :Base, 'controll/notify/base'
|
|
4
|
+
autoload :Flash, 'controll/notify/flash'
|
|
5
|
+
autoload :Typed, 'controll/notify/typed'
|
|
6
|
+
autoload :Macros, 'controll/notify/macros'
|
|
7
|
+
autoload :Message, 'controll/notify/message'
|
|
6
8
|
end
|
|
7
|
-
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module Notifiers
|
|
12
|
+
Typed = Controll::Notify::Typed
|
|
13
|
+
Notifier = Controll::Notify::Typed
|
|
14
|
+
end
|
data/lib/controll.rb
CHANGED
|
@@ -4,11 +4,17 @@ end
|
|
|
4
4
|
require 'hashie'
|
|
5
5
|
require 'imperator-ext'
|
|
6
6
|
require 'controll/errors'
|
|
7
|
+
require 'controll/event'
|
|
8
|
+
require 'controll/events'
|
|
9
|
+
require 'controll/assistant'
|
|
7
10
|
require 'controll/executor'
|
|
8
11
|
require 'controll/notify'
|
|
9
|
-
require 'controll/
|
|
12
|
+
require 'controll/flow'
|
|
10
13
|
require 'controll/helper'
|
|
14
|
+
require 'controll/enabler'
|
|
11
15
|
require 'controll/command'
|
|
12
16
|
require 'controll/commander'
|
|
13
|
-
require 'controll/
|
|
17
|
+
require 'controll/macros'
|
|
18
|
+
|
|
19
|
+
require 'controll/engine' if defined?(::Rails::Engine)
|
|
14
20
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Controll
|
|
2
|
+
module Generators
|
|
3
|
+
class AssistantGenerator < ::Rails::Generators::NamedBase
|
|
4
|
+
desc 'Generates an Assitant'
|
|
5
|
+
|
|
6
|
+
class_option :delegate, type: :boolean, default: false
|
|
7
|
+
|
|
8
|
+
def main_flow
|
|
9
|
+
template "assistant.tt", "app/controll/assistants/#{file_name}.rb"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
protected
|
|
13
|
+
|
|
14
|
+
def delegate?
|
|
15
|
+
options[:delegate]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parent_class
|
|
19
|
+
name.include?('::') ? "::Controll::#{parent_class_name}" : parent_class_name
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def parent_class_name
|
|
23
|
+
delegate? 'DelegateAssistant' : 'Assistant'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Controll
|
|
2
|
+
module Generators
|
|
3
|
+
class ExecutorGenerator < ::Rails::Generators::NamedBase
|
|
4
|
+
desc 'Generates an Executor'
|
|
5
|
+
|
|
6
|
+
class_option :type, default: 'base', desc: 'The type of executor'
|
|
7
|
+
|
|
8
|
+
def main_flow
|
|
9
|
+
template 'executor.tt', "app/controll/executors/#{file_name}.rb"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
protected
|
|
13
|
+
|
|
14
|
+
def parent_class
|
|
15
|
+
name.include?('::') ? "::Controll::Executor::#{parent_class_name}" : parent_class_name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parent_class_name
|
|
19
|
+
(options[:type] || 'base').camelize
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|