Class: Smooth::Command
- Includes:
- Instrumented
- Defined in:
- lib/smooth/command.rb,
lib/smooth/command/run_proxy.rb,
lib/smooth/command/instrumented.rb
Direct Known Subclasses
Defined Under Namespace
Modules: Instrumented Classes: AsyncWorker, RunProxy
Constant Summary collapse
- Patterns =
{}
Instance Attribute Summary collapse
-
#current_user ⇒ Object
Commands are aware of who is running them.
Class Method Summary collapse
- .as(current_user) ⇒ Object
- .base_scope ⇒ Object
- .belongs_to_resource(resource) ⇒ Object
-
.configure(dsl_config_object, resource = nil) ⇒ Object
DSL Hooks.
- .define_or_open(options, resource) ⇒ Object
- .event_namespace ⇒ Object
-
.execute(execution_pattern = nil, &block) ⇒ Object
Allows for defining common execution pattern methods mostly for standard CRUD against scoped models.
- .filter_for_param(param) ⇒ Object
- .filter_options_for_param(param) ⇒ Object
- .find_serializer_for(_request_object) ⇒ Object
- .get_execution_pattern(pattern_name) ⇒ Object
- .input_argument_names ⇒ Object
- .interface(*args, &block) ⇒ Object
- .interface_description ⇒ Object
- .interface_documentation ⇒ Object
- .object_path ⇒ Object
-
.params(*args, &block) ⇒ Object
DSL Improvements English.
- .parent_api ⇒ Object
- .resource_alias ⇒ Object
- .resource_name ⇒ Object
-
.respond_to_request(request_object, options = {}) ⇒ Object
Creates a new instance of the Smooth::Command::Response class in response to a request from the Router.
- .response_class ⇒ Object
- .scope(setting = nil) ⇒ Object
- .serializer_options ⇒ Object
Instance Method Summary collapse
- #event_namespace ⇒ Object
-
#interface_for(filter) ⇒ Object
Interface Documentation.
- #model_class ⇒ Object
- #object_path ⇒ Object
- #parent_api ⇒ Object
- #parent_resource ⇒ Object
- #resource_alias ⇒ Object
- #resource_name ⇒ Object
-
#scope(*args) ⇒ Object
Returns the model scope for this command.
- #scope=(new_scope) ⇒ Object
- #scoped_find_object ⇒ Object
Methods included from Instrumented
included, #run_with_instrumentation, #run_with_outcome
Instance Attribute Details
#current_user ⇒ Object
Commands are aware of who is running them
23 24 25 |
# File 'lib/smooth/command.rb', line 23 def current_user @current_user end |
Class Method Details
.as(current_user) ⇒ Object
4 5 6 7 |
# File 'lib/smooth/command.rb', line 4 def self.as(current_user) require 'smooth/command/run_proxy' unless defined?(RunProxy) RunProxy.new(current_user, self) end |
.base_scope ⇒ Object
32 33 34 |
# File 'lib/smooth/command.rb', line 32 def self.base_scope @base_scope || :all end |
.belongs_to_resource(resource) ⇒ Object
44 45 46 |
# File 'lib/smooth/command.rb', line 44 def self.belongs_to_resource(resource) self.parent_resource = resource end |
.configure(dsl_config_object, resource = nil) ⇒ Object
DSL Hooks
124 125 126 127 128 129 130 131 132 133 |
# File 'lib/smooth/command.rb', line 124 def self.configure(dsl_config_object, resource = nil) resource ||= Smooth.current_resource klass = define_or_open(dsl_config_object, resource) Array(dsl_config_object.blocks).each do |blk| klass.class_eval(&blk) end klass end |
.define_or_open(options, resource) ⇒ Object
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/smooth/command.rb', line 135 def self.define_or_open(, resource) resource_name = resource.name.to_s.singularize base = Smooth.command name = .name.to_s.camelize klass = "#{ name }#{ resource.model_class }".gsub(/\s+/, '') = lambda do |k| k.model_class ||= resource.model_class if resource.model_class k.belongs_to_resource(resource) k.resource_name = resource.name.to_s k.command_action = .name.to_s end if command_klass = Object.const_get(klass) rescue nil return command_klass.tap(&) end parent_klass = Class.new(base) begin Object.const_set(klass, parent_klass).tap(&) rescue => ex puts ex. puts "Error setting #{ klass } #{ base }. klass is a #{ klass.class }" end parent_klass end |
.event_namespace ⇒ Object
79 80 81 |
# File 'lib/smooth/command.rb', line 79 def self.event_namespace @event_namespace || "#{ command_action }.#{ resource_alias }".downcase end |
.execute(execution_pattern = nil, &block) ⇒ Object
Allows for defining common execution pattern methods mostly for standard CRUD against scoped models
267 268 269 |
# File 'lib/smooth/command.rb', line 267 def self.execute(execution_pattern = nil, &block) send :define_method, :execute, (block || get_execution_pattern(execution_pattern)) end |
.filter_for_param(param) ⇒ Object
217 218 219 |
# File 'lib/smooth/command.rb', line 217 def self.filter_for_param(param) optional_inputs[param] || required_inputs[param] end |
.filter_options_for_param(param) ⇒ Object
221 222 223 |
# File 'lib/smooth/command.rb', line 221 def self.(param) filter_for_param(param).try(:options) end |
.find_serializer_for(_request_object) ⇒ Object
248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/smooth/command.rb', line 248 def self.find_serializer_for(_request_object) resource = Smooth.resource(resource_name) resource ||= Smooth.resource("#{ resource_name }".pluralize) # TODO # We can make the preferred format something you can # specify via a header or parameter. We can also restrict # certain serializers from certain policies. preferred_format = :default resource.fetch(:serializer, preferred_format) end |
.get_execution_pattern(pattern_name) ⇒ Object
295 296 297 298 299 300 301 302 303 |
# File 'lib/smooth/command.rb', line 295 def self.get_execution_pattern(pattern_name) if respond_to?("#{ pattern_name }_execution_pattern") return method("#{ pattern_name }_execution_pattern").to_proc elsif Patterns.key?(pattern_name.to_sym) Patterns.fetch(pattern_name.to_sym) else return method(:execute).to_proc end end |
.input_argument_names ⇒ Object
18 19 20 |
# File 'lib/smooth/command.rb', line 18 def self.input_argument_names required_inputs.keys + optional_inputs.keys end |
.interface(*args, &block) ⇒ Object
14 15 16 |
# File 'lib/smooth/command.rb', line 14 def self.interface(*args, &block) send(:required, *args, &block) end |
.interface_description ⇒ Object
173 174 175 |
# File 'lib/smooth/command.rb', line 173 def self.interface_description interface_documentation end |
.interface_documentation ⇒ Object
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/smooth/command.rb', line 177 def self.interface_documentation optional_inputs = input_filters.optional_inputs required_inputs = input_filters.required_inputs data = { required: required_inputs.keys, optional: optional_inputs.keys, filters: {} } blk = lambda do |memo, parts, required| key, filter = parts type = filter.class.name[/^Mutations::([a-zA-Z]*)Filter$/, 1].underscore = filter..merge(required: required) value = memo[key] = { type: type, options: .reject { |_k, v| v.nil? }, description: input_descriptions[key] } if [:faker] value[:example] = Smooth.faker([:faker]) end memo end required_inputs.reduce(data[:filters]) do |memo, parts| blk.call(memo, parts, true) end optional_inputs.reduce(data[:filters]) do |memo, parts| blk.call(memo, parts, false) end data.to_mash end |
.object_path ⇒ Object
97 98 99 |
# File 'lib/smooth/command.rb', line 97 def self.object_path resource_name.downcase + '.' + command_action end |
.params(*args, &block) ⇒ Object
DSL Improvements English
10 11 12 |
# File 'lib/smooth/command.rb', line 10 def self.params(*args, &block) send(:required, *args, &block) end |
.parent_api ⇒ Object
48 49 50 |
# File 'lib/smooth/command.rb', line 48 def self.parent_api parent_resource.api end |
.resource_alias ⇒ Object
83 84 85 |
# File 'lib/smooth/command.rb', line 83 def self.resource_alias resource_name.singularize.underscore end |
.resource_name ⇒ Object
87 88 89 90 91 92 93 94 95 |
# File 'lib/smooth/command.rb', line 87 def self.resource_name value = @resource_name.to_s if value.empty? && model_class value = model_class.to_s end value end |
.respond_to_request(request_object, options = {}) ⇒ Object
Creates a new instance of the Smooth::Command::Response class in response to a request from the Router. It is assumed that a request object responds to: user, and params
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/smooth/command.rb', line 232 def self.respond_to_request(request_object, = {}) klass = self outcome = .fetch(:outcome) do klass.as(request_object.user).run(request_object.params) end response_class.new(outcome, ).tap do |response| response.request_headers = request_object.headers response.serializer = find_serializer_for(request_object) response.event_namespace = event_namespace response.command_action = command_action response.current_user = request_object.user end end |
.response_class ⇒ Object
225 226 227 |
# File 'lib/smooth/command.rb', line 225 def self.response_class Smooth::Response end |
.scope(setting = nil) ⇒ Object
74 75 76 77 |
# File 'lib/smooth/command.rb', line 74 def self.scope(setting = nil) self.base_scope = setting if setting base_scope || :all end |
.serializer_options ⇒ Object
261 262 263 |
# File 'lib/smooth/command.rb', line 261 def self. {} end |
Instance Method Details
#event_namespace ⇒ Object
101 102 103 |
# File 'lib/smooth/command.rb', line 101 def event_namespace self.class.event_namespace end |
#interface_for(filter) ⇒ Object
Interface Documentation
169 170 171 |
# File 'lib/smooth/command.rb', line 169 def interface_for(filter) self.class.interface_description.filters.send(filter) end |
#model_class ⇒ Object
117 118 119 |
# File 'lib/smooth/command.rb', line 117 def model_class self.class.model_class end |
#object_path ⇒ Object
105 106 107 |
# File 'lib/smooth/command.rb', line 105 def object_path self.class.object_path end |
#parent_api ⇒ Object
36 37 38 |
# File 'lib/smooth/command.rb', line 36 def parent_api self.class.parent_api end |
#parent_resource ⇒ Object
40 41 42 |
# File 'lib/smooth/command.rb', line 40 def parent_resource self.class.parent_resource end |
#resource_alias ⇒ Object
113 114 115 |
# File 'lib/smooth/command.rb', line 113 def resource_alias self.class.resource_alias end |
#resource_name ⇒ Object
109 110 111 |
# File 'lib/smooth/command.rb', line 109 def resource_name self.class.resource_name end |
#scope(*args) ⇒ Object
Returns the model scope for this command. If a scope method is set on this command, it will make sure to scope the model by that method. It will pass whatever arguments you pass to scope to the scope method. if you pass no args, and the scope requires one, we will assume the user wants us to pass the current user of the command
57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/smooth/command.rb', line 57 def scope(*args) @scope ||= begin meth = model_class.send(:method, self.class.base_scope) if meth.arity.abs >= 1 args.push(current_user) if args.empty? model_class.send(self.class.base_scope, *args) else model_class.send(self.class.base_scope) end end end |
#scope=(new_scope) ⇒ Object
70 71 72 |
# File 'lib/smooth/command.rb', line 70 def scope=(new_scope) @scope = new_scope || scope end |
#scoped_find_object ⇒ Object
287 288 289 290 291 292 293 |
# File 'lib/smooth/command.rb', line 287 def scoped_find_object @scoped_find ||= if scope.respond_to?(:find) && found = (scope.find(id) rescue nil) found else add_error(:id, :not_found, "could not find a #{ resource_name } model with that id") end end |