appfuel 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +25 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +19 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +9 -0
- data/README.md +38 -0
- data/Rakefile +6 -0
- data/appfuel.gemspec +42 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/lib/appfuel.rb +210 -0
- data/lib/appfuel/application.rb +4 -0
- data/lib/appfuel/application/app_container.rb +223 -0
- data/lib/appfuel/application/container_class_registration.rb +22 -0
- data/lib/appfuel/application/container_key.rb +201 -0
- data/lib/appfuel/application/qualify_container_key.rb +76 -0
- data/lib/appfuel/application/root.rb +140 -0
- data/lib/appfuel/cli_msg_request.rb +19 -0
- data/lib/appfuel/configuration.rb +14 -0
- data/lib/appfuel/configuration/definition_dsl.rb +175 -0
- data/lib/appfuel/configuration/file_loader.rb +61 -0
- data/lib/appfuel/configuration/populate.rb +95 -0
- data/lib/appfuel/configuration/search.rb +45 -0
- data/lib/appfuel/db_model.rb +16 -0
- data/lib/appfuel/domain.rb +7 -0
- data/lib/appfuel/domain/criteria.rb +436 -0
- data/lib/appfuel/domain/domain_name_parser.rb +44 -0
- data/lib/appfuel/domain/dsl.rb +247 -0
- data/lib/appfuel/domain/entity.rb +242 -0
- data/lib/appfuel/domain/entity_collection.rb +87 -0
- data/lib/appfuel/domain/expr.rb +127 -0
- data/lib/appfuel/domain/value_object.rb +7 -0
- data/lib/appfuel/errors.rb +104 -0
- data/lib/appfuel/feature.rb +2 -0
- data/lib/appfuel/feature/action_loader.rb +25 -0
- data/lib/appfuel/feature/initializer.rb +43 -0
- data/lib/appfuel/handler.rb +6 -0
- data/lib/appfuel/handler/action.rb +17 -0
- data/lib/appfuel/handler/base.rb +103 -0
- data/lib/appfuel/handler/command.rb +18 -0
- data/lib/appfuel/handler/inject_dsl.rb +88 -0
- data/lib/appfuel/handler/validator_dsl.rb +256 -0
- data/lib/appfuel/initialize.rb +70 -0
- data/lib/appfuel/initialize/initializer.rb +68 -0
- data/lib/appfuel/msg_request.rb +207 -0
- data/lib/appfuel/predicates.rb +10 -0
- data/lib/appfuel/presenter.rb +18 -0
- data/lib/appfuel/presenter/base.rb +7 -0
- data/lib/appfuel/repository.rb +73 -0
- data/lib/appfuel/repository/base.rb +72 -0
- data/lib/appfuel/repository/initializer.rb +19 -0
- data/lib/appfuel/repository/mapper.rb +203 -0
- data/lib/appfuel/repository/mapping_dsl.rb +210 -0
- data/lib/appfuel/repository/mapping_entry.rb +76 -0
- data/lib/appfuel/repository/mapping_registry.rb +121 -0
- data/lib/appfuel/repository_runner.rb +60 -0
- data/lib/appfuel/request.rb +53 -0
- data/lib/appfuel/response.rb +96 -0
- data/lib/appfuel/response_handler.rb +79 -0
- data/lib/appfuel/root_module.rb +31 -0
- data/lib/appfuel/run_error.rb +9 -0
- data/lib/appfuel/storage.rb +3 -0
- data/lib/appfuel/storage/db.rb +4 -0
- data/lib/appfuel/storage/db/active_record_model.rb +42 -0
- data/lib/appfuel/storage/db/mapper.rb +213 -0
- data/lib/appfuel/storage/db/migration_initializer.rb +42 -0
- data/lib/appfuel/storage/db/migration_runner.rb +15 -0
- data/lib/appfuel/storage/db/migration_tasks.rb +18 -0
- data/lib/appfuel/storage/db/repository.rb +231 -0
- data/lib/appfuel/storage/db/repository_query.rb +13 -0
- data/lib/appfuel/storage/file.rb +1 -0
- data/lib/appfuel/storage/file/base.rb +32 -0
- data/lib/appfuel/storage/memory.rb +2 -0
- data/lib/appfuel/storage/memory/mapper.rb +30 -0
- data/lib/appfuel/storage/memory/repository.rb +37 -0
- data/lib/appfuel/types.rb +53 -0
- data/lib/appfuel/validation.rb +80 -0
- data/lib/appfuel/validation/validator.rb +59 -0
- data/lib/appfuel/validation/validator_pipe.rb +47 -0
- data/lib/appfuel/version.rb +3 -0
- metadata +335 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module Appfuel
|
2
|
+
module Application
|
3
|
+
module ContainerClassRegistration
|
4
|
+
# All handlers are automatically registered into the application
|
5
|
+
# container which allows them to easily be retrieved for execution.
|
6
|
+
# The ContainerKey mixin handles converting ruby class namespaces to
|
7
|
+
# container key, so we simply need to obtain the qualified namespace
|
8
|
+
# key for this class extending this, that does not belong to appfuel.
|
9
|
+
#
|
10
|
+
# @param klass [Class] the handler class that is inheriting this
|
11
|
+
# @return [Boolean]
|
12
|
+
def register_container_class(klass)
|
13
|
+
root = klass.container_root_name
|
14
|
+
return false if root == 'appfuel'
|
15
|
+
|
16
|
+
container = Appfuel.app_container(root)
|
17
|
+
container.register(klass.container_qualified_key, klass)
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
module Appfuel
|
2
|
+
module Application
|
3
|
+
# Mixins to allow you to handle application container keys. The application
|
4
|
+
# container operates based on certain conventions which we take into account
|
5
|
+
# here.
|
6
|
+
module ContainerKey
|
7
|
+
# Parse the namespace assuming it is a ruby namespace and assign
|
8
|
+
# the list to container_path_list
|
9
|
+
#
|
10
|
+
# @param namespace [String]
|
11
|
+
# @return [Array]
|
12
|
+
def load_path_from_ruby_namespace(namespace)
|
13
|
+
self.container_path = parse_list_string(namespace, '::')
|
14
|
+
end
|
15
|
+
|
16
|
+
# Parse the namespace assuming it is a dry container namespace and
|
17
|
+
# assign the list to container_path_list
|
18
|
+
#
|
19
|
+
# @param namespace [String]
|
20
|
+
# @return [Array]
|
21
|
+
def load_path_from_container_namespace(namespace)
|
22
|
+
self.container_path = parse_list_string(namespace, '.')
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param namespace [String] encoded string that represents a path
|
26
|
+
# @param char [String] character used to split the keys into a list
|
27
|
+
# @return [Array] an array of lower case snake cased strings
|
28
|
+
def parse_list_string(namespace, char)
|
29
|
+
fail "split char must be '.' or '::'" unless ['.', '::'].include?(char)
|
30
|
+
namespace.to_s.split(char).map {|i| i.underscore }
|
31
|
+
end
|
32
|
+
|
33
|
+
# return [Boolean]
|
34
|
+
def container_path?
|
35
|
+
!@container_path.nil?
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param list [Array] list of container namespace parts including root
|
39
|
+
# @return [Array]
|
40
|
+
def container_path=(list)
|
41
|
+
fail "container path list must be an array" unless list.is_a?(Array)
|
42
|
+
@container_path = list
|
43
|
+
@container_path.freeze
|
44
|
+
end
|
45
|
+
|
46
|
+
# An array representation of the application container namespace, where
|
47
|
+
# the root is the name of the application and not part of the namespace
|
48
|
+
# and the rest is hierarchical path to features or globals
|
49
|
+
#
|
50
|
+
# @return [Array]
|
51
|
+
def container_path
|
52
|
+
load_path_from_ruby_namespace(self.to_s) unless container_path?
|
53
|
+
@container_path
|
54
|
+
end
|
55
|
+
|
56
|
+
# This is the application name used to identify the application container
|
57
|
+
# that is stored in the framework container
|
58
|
+
#
|
59
|
+
# @return string
|
60
|
+
def container_root_name
|
61
|
+
@container_root_name ||= container_path.first
|
62
|
+
end
|
63
|
+
|
64
|
+
# All root namespace for anything inside features, use this name. It is
|
65
|
+
# important to note that to avoid long namespace in ruby features are the
|
66
|
+
# name of the module directly below the root.
|
67
|
+
#
|
68
|
+
# @return [String]
|
69
|
+
def container_features_root_name
|
70
|
+
@container_features_root_name ||= 'features'
|
71
|
+
end
|
72
|
+
|
73
|
+
# The actual name of the feature
|
74
|
+
#
|
75
|
+
# @return [String]
|
76
|
+
def container_feature_name
|
77
|
+
container_path[1]
|
78
|
+
end
|
79
|
+
|
80
|
+
# The feature name is the second item in the path, that is always prexfix
|
81
|
+
# with "features"
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
def container_feature_key
|
85
|
+
@container_feature_key ||= (
|
86
|
+
"#{container_features_root_name}.#{container_feature_name}"
|
87
|
+
)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Container key relative from feature or global, depending on which class
|
91
|
+
# this is mixed into
|
92
|
+
#
|
93
|
+
# @return [String]
|
94
|
+
def container_relative_key
|
95
|
+
@container_relative_key ||= container_path[2..-1].join('.')
|
96
|
+
end
|
97
|
+
|
98
|
+
# This refers to either the global path or the path to a particular
|
99
|
+
# feature
|
100
|
+
#
|
101
|
+
# @return [String]
|
102
|
+
def top_container_key
|
103
|
+
container_global_path? ? container_global_name : container_feature_key
|
104
|
+
end
|
105
|
+
|
106
|
+
def container_key_basename
|
107
|
+
@container_path.last
|
108
|
+
end
|
109
|
+
|
110
|
+
# Fully qualified key, meaning you can access the class this was mixed into
|
111
|
+
# if you stored it into the container using this key
|
112
|
+
#
|
113
|
+
# @return [String]
|
114
|
+
def container_qualified_key
|
115
|
+
@container_qualified_key ||= (
|
116
|
+
"#{top_container_key}.#{container_relative_key}"
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Determines if the container path represents a global glass
|
121
|
+
#
|
122
|
+
# @return [Boolean]
|
123
|
+
def container_global_path?
|
124
|
+
container_path[1] == container_global_name
|
125
|
+
end
|
126
|
+
|
127
|
+
# @return [String]
|
128
|
+
def container_global_name
|
129
|
+
@container_global_name ||= 'global'
|
130
|
+
end
|
131
|
+
|
132
|
+
# Convert the injection key to a fully qualified namespaced key that
|
133
|
+
# is used to pull an item out of the app container.
|
134
|
+
#
|
135
|
+
# Rules:
|
136
|
+
# 1) split the injection key by '.'
|
137
|
+
# 2) use the feature_key as the initial namespace
|
138
|
+
# 3) when the first part of the key is "global" use that instead of
|
139
|
+
# the feature_key
|
140
|
+
# 4) append the type_key to the namespace unless it is "container"
|
141
|
+
# type_key like "repositories" or "commands" removes the need for
|
142
|
+
# the user to have to specify it since they already did that when
|
143
|
+
# they used the type param.
|
144
|
+
#
|
145
|
+
#
|
146
|
+
# note: feature_key in these examples will be "features.my-feature"
|
147
|
+
# @example of a feature repository named foo
|
148
|
+
#
|
149
|
+
# convert_to_qualified_container_key('foo', 'repositories')
|
150
|
+
#
|
151
|
+
# returns 'features.my-feature.repositories.foo'
|
152
|
+
#
|
153
|
+
# @example of a global command names bar
|
154
|
+
#
|
155
|
+
# convert_to_qualified_container_key('global.bar', 'commands')
|
156
|
+
#
|
157
|
+
# returns 'gloval.commands.bar'
|
158
|
+
#
|
159
|
+
# @example of a container item baz
|
160
|
+
# NOTE: feature container items are not in any namespace, they are any item
|
161
|
+
# that can resolve from the namespace given by "feature_key"
|
162
|
+
#
|
163
|
+
# convert_to_qualified_container_key('baz', 'container')
|
164
|
+
#
|
165
|
+
# returns 'features.my-feature.baz'
|
166
|
+
#
|
167
|
+
# @example of a global container item baz
|
168
|
+
# NOTE: global container items are not in any namespace, they are any item
|
169
|
+
# you can resolve from the application container.
|
170
|
+
#
|
171
|
+
# convert_to_qualified_container_key('global.baz', 'container')
|
172
|
+
#
|
173
|
+
# returns 'baz'
|
174
|
+
#
|
175
|
+
# @param key [String] partial key to be built into fully qualified key
|
176
|
+
# @param type_ns [String] namespace for key
|
177
|
+
# @return [String] fully qualified namespaced key
|
178
|
+
def qualify_container_key(key, type_ns)
|
179
|
+
parts = key.to_s.split('.')
|
180
|
+
namespace = "#{container_feature_key}."
|
181
|
+
if parts[0].downcase == 'global'
|
182
|
+
namespace = 'global.'
|
183
|
+
parts.shift
|
184
|
+
elsif parts[0] == container_feature_name
|
185
|
+
parts.shift
|
186
|
+
end
|
187
|
+
|
188
|
+
# when the key is a global container the namespace is only the path
|
189
|
+
if type_ns == "container"
|
190
|
+
namespace = '' if namespace == 'global.'
|
191
|
+
type_ns = ''
|
192
|
+
else
|
193
|
+
type_ns = "#{type_ns}."
|
194
|
+
end
|
195
|
+
|
196
|
+
path = parts.join('.')
|
197
|
+
"#{namespace}#{type_ns}#{path}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Appfuel
|
2
|
+
module Application
|
3
|
+
# Mixins to allow you to handle application container keys. The application
|
4
|
+
# container operates based on certain conventions which we take into account
|
5
|
+
# here.
|
6
|
+
module QualifyContainerKey
|
7
|
+
# Convert the injection key to a fully qualified namespaced key that
|
8
|
+
# is used to pull an item out of the app container.
|
9
|
+
#
|
10
|
+
# Rules:
|
11
|
+
# 1) split the injection key by '.'
|
12
|
+
# 2) use the feature_key as the initial namespace
|
13
|
+
# 3) when the first part of the key is "global" use that instead of
|
14
|
+
# the feature_key
|
15
|
+
# 4) append the type_key to the namespace unless it is "container"
|
16
|
+
# type_key like "repositories" or "commands" removes the need for
|
17
|
+
# the user to have to specify it since they already did that when
|
18
|
+
# they used the type param.
|
19
|
+
#
|
20
|
+
#
|
21
|
+
# note: feature_key in these examples will be "features.my-feature"
|
22
|
+
# @example of a feature repository named foo
|
23
|
+
#
|
24
|
+
# convert_to_qualified_container_key('foo', 'repositories')
|
25
|
+
#
|
26
|
+
# returns 'features.my-feature.repositories.foo'
|
27
|
+
#
|
28
|
+
# @example of a global command names bar
|
29
|
+
#
|
30
|
+
# convert_to_qualified_container_key('global.bar', 'commands')
|
31
|
+
#
|
32
|
+
# returns 'gloval.commands.bar'
|
33
|
+
#
|
34
|
+
# @example of a container item baz
|
35
|
+
# NOTE: feature container items are not in any namespace, they are any item
|
36
|
+
# that can resolve from the namespace given by "feature_key"
|
37
|
+
#
|
38
|
+
# convert_to_qualified_container_key('baz', 'container')
|
39
|
+
#
|
40
|
+
# returns 'features.my-feature.baz'
|
41
|
+
#
|
42
|
+
# @example of a global container item baz
|
43
|
+
# NOTE: global container items are not in any namespace, they are any item
|
44
|
+
# you can resolve from the application container.
|
45
|
+
#
|
46
|
+
# convert_to_qualified_container_key('global.baz', 'container')
|
47
|
+
#
|
48
|
+
# returns 'baz'
|
49
|
+
#
|
50
|
+
# @param key [String] partial key to be built into fully qualified key
|
51
|
+
# @param type_ns [String] namespace for key
|
52
|
+
# @return [String] fully qualified namespaced key
|
53
|
+
def qualify_container_key(key, type_ns)
|
54
|
+
parts = key.to_s.split('.')
|
55
|
+
namespace = "#{container_feature_key}."
|
56
|
+
if parts[0].downcase == 'global'
|
57
|
+
namespace = 'global.'
|
58
|
+
parts.shift
|
59
|
+
elsif parts[0] == container_feature_name
|
60
|
+
parts.shift
|
61
|
+
end
|
62
|
+
|
63
|
+
# when the key is a global container the namespace is only the path
|
64
|
+
if type_ns == "container"
|
65
|
+
namespace = '' if namespace == 'global.'
|
66
|
+
type_ns = ''
|
67
|
+
else
|
68
|
+
type_ns = "#{type_ns}."
|
69
|
+
end
|
70
|
+
|
71
|
+
path = parts.join('.')
|
72
|
+
"#{namespace}#{type_ns}#{path}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Appfuel
|
2
|
+
module Application
|
3
|
+
module Root
|
4
|
+
# Initialize Appfuel by creating an application container for the
|
5
|
+
# app represented by the root module passed in. The app container is
|
6
|
+
# a dependency injection container that is used thought the app.
|
7
|
+
#
|
8
|
+
# @raises ArgumentError when root module does not exist
|
9
|
+
#
|
10
|
+
# @param params [Hash]
|
11
|
+
# @option root [Module] root module of the application
|
12
|
+
# @option app_name [String, Symbol] key to store container in appfuel
|
13
|
+
#
|
14
|
+
# @return [Dry::Container]
|
15
|
+
def setup_appfuel(params = {})
|
16
|
+
app_container = params[:app_container] || Dry::Container.new
|
17
|
+
framework_container = Appfuel.framework_container
|
18
|
+
|
19
|
+
app_container = build_app_container(params, app_container)
|
20
|
+
app_name = handle_app_name(params, app_container, framework_container)
|
21
|
+
|
22
|
+
app_container.register(:app_name, app_name)
|
23
|
+
framework_container.register(app_name, app_container)
|
24
|
+
|
25
|
+
if params.key?(:on_after_setup)
|
26
|
+
handle_after_setup(params[:on_after_setup], app_container)
|
27
|
+
end
|
28
|
+
|
29
|
+
app_container
|
30
|
+
end
|
31
|
+
|
32
|
+
def handle_after_setup(hook, container)
|
33
|
+
unless hook.respond_to?(:call)
|
34
|
+
fail ArgumentError, "After setup hook (:after_setup) must " +
|
35
|
+
"implement :call, which takes the di container as its only arg"
|
36
|
+
end
|
37
|
+
hook.call(container)
|
38
|
+
end
|
39
|
+
|
40
|
+
# The application name is determined by the root module. We use the
|
41
|
+
# lower case underscored version of the root module name
|
42
|
+
#
|
43
|
+
# @param root [Module] The root module of the application
|
44
|
+
# @param params [Hash] input params from setup
|
45
|
+
# @option app_name [String] optional
|
46
|
+
# @option default_app [Bool] force the assignment of default name
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
def handle_app_name(params, app_container, framework_container)
|
50
|
+
app_name = app_container[:root].to_s.underscore
|
51
|
+
|
52
|
+
if params[:default_app] == true || !Appfuel.default_app?
|
53
|
+
framework_container.register(:default_app_name, app_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
app_name
|
57
|
+
end
|
58
|
+
|
59
|
+
# Initializes the application container with:
|
60
|
+
#
|
61
|
+
# Application Container
|
62
|
+
# root: This is the root module that holds the namespaces for all
|
63
|
+
# features, actions, commands etc. This is required.
|
64
|
+
#
|
65
|
+
# root_path: This is the root path of app where the source code
|
66
|
+
# lives. We use this to autoload this features. This
|
67
|
+
# is still under design so it might not stay.
|
68
|
+
#
|
69
|
+
# config_definition: This is the definition object that we use to
|
70
|
+
# build out the configuration hash. This is optional
|
71
|
+
#
|
72
|
+
# initializers: This is an array that hold all the initializers to be
|
73
|
+
# run. This builder will handle creating the array. It is
|
74
|
+
# populated via appfuel dsl Appfuel::Initialize#define
|
75
|
+
#
|
76
|
+
# global.validators: This is a hash that holds all global validators.
|
77
|
+
# this builder will handle creating the hash. It is
|
78
|
+
# populated via appfuel dsl
|
79
|
+
# Appfuel::Validator#global_validator
|
80
|
+
#
|
81
|
+
# global.domain_builders:
|
82
|
+
# global.presenters
|
83
|
+
#
|
84
|
+
# @param root [Module] the root module of the application
|
85
|
+
# @param container [Dry::Container] dependency injection container
|
86
|
+
# @return [Dry::Container]
|
87
|
+
def build_app_container(params, container = Dry::Container.new)
|
88
|
+
root = params.fetch(:root) {
|
89
|
+
fail ArgumentError, "Root module (:root) is required"
|
90
|
+
}
|
91
|
+
|
92
|
+
root_path = params.fetch(:root_path) {
|
93
|
+
fail ArgumentError, "Root path (:root_path) is required"
|
94
|
+
}
|
95
|
+
|
96
|
+
feature_initializer = params.fetch(:feature_initializer) {
|
97
|
+
Feature::Initializer.new
|
98
|
+
}
|
99
|
+
|
100
|
+
action_loader = params.fetch(:action_loader) {
|
101
|
+
Feature::ActionLoader.new
|
102
|
+
}
|
103
|
+
|
104
|
+
repo_initializer = params.fetch(:repository_initializer) {
|
105
|
+
Repository::Initializer.new
|
106
|
+
}
|
107
|
+
|
108
|
+
root_name = root.to_s.underscore
|
109
|
+
container.register(:root, root)
|
110
|
+
container.register(:root_name, root_name)
|
111
|
+
container.register(:root_path, root_path)
|
112
|
+
container.register(:repository_mappings, {})
|
113
|
+
container.register(:repository_initializer, repo_initializer)
|
114
|
+
container.register(:features_path, "#{root_name}/features")
|
115
|
+
container.register(:feature_initializer, feature_initializer)
|
116
|
+
container.register(:action_loader, action_loader)
|
117
|
+
if params.key?(:config_definition)
|
118
|
+
container.register(:config_definition, params[:config_definition])
|
119
|
+
end
|
120
|
+
|
121
|
+
Appfuel.setup_container_dependencies('global', container)
|
122
|
+
|
123
|
+
container
|
124
|
+
end
|
125
|
+
|
126
|
+
def bootstrap(overrides: {}, env: ENV)
|
127
|
+
Initialize.run(overrides: overrides, env: env)
|
128
|
+
end
|
129
|
+
|
130
|
+
def call(route, inputs = {})
|
131
|
+
container = Appfuel.app_container
|
132
|
+
request = Request.new(route, inputs)
|
133
|
+
|
134
|
+
container[:feature_initializer].call(request.feature, container)
|
135
|
+
action = container[:action_loader].call(request.namespace, container)
|
136
|
+
action.run(inputs)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Appfuel
|
2
|
+
# This represents the message delivered by RabbitMQ. We encapsulate it
|
3
|
+
# so that if you want to fire an action from the command line you can
|
4
|
+
# use a CliRequest and not worry about rabbit details
|
5
|
+
#
|
6
|
+
class CliMsgRequest < MsgRequest
|
7
|
+
|
8
|
+
def initialize (route, input)
|
9
|
+
self.inputs = input
|
10
|
+
self.service_route = route
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def inputs=(data)
|
15
|
+
fail "input must be a hash" unless data.is_a?(Hash)
|
16
|
+
@inputs = data
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|