Class: Operations::Command
- Inherits:
-
Object
- Object
- Operations::Command
- Extended by:
- Dry::Initializer
- Defined in:
- lib/operations/command.rb
Overview
should they ever happen.
Defined Under Namespace
Classes: OperationFailed
Constant Summary collapse
- UNDEFINED =
Object.new.freeze
- EMPTY_HASH =
{}.freeze
- COMPONENTS =
%i[contract policies idempotency preconditions operation on_success on_failure].freeze
- FORM_HYDRATOR =
->(_form_class, params, **_context) { params }
Class Method Summary collapse
-
.build(operation, contract = nil, **deps) ⇒ Object
A short-cut to initialize operation by convention:.
Instance Method Summary collapse
-
#allowed(params = EMPTY_HASH, **context) ⇒ Object
Works the same way as
callablebut checks only the policy. - #as_json ⇒ Object
-
#call(params, **context) ⇒ Object
Executes all the components in a particular order.
-
#call!(params, **context) ⇒ Object
Works the same way as
callbut raises an exception on operation failure. -
#callable(params = EMPTY_HASH, **context) ⇒ Object
Checks if the operation is possible to call in the current context.
-
#initialize(operation, policy: UNDEFINED, policies: [UNDEFINED], precondition: nil, preconditions: [], after: [], **options) ⇒ Command
constructor
A new instance of Command.
-
#merge(**changes) ⇒ Object
Instantiates a new command with the given fields updated.
-
#possible(params = EMPTY_HASH, **context) ⇒ Object
Works the same way as
callablebut checks only preconditions. - #pretty_print(pp) ⇒ Object
-
#try_call!(params, **context) ⇒ Object
Calls the operation and raises an exception in case of a failure but only if preconditions and policies have passed.
-
#valid?(*args, **kwargs) ⇒ Boolean
Returns boolean result instead of Operations::Result for validate method.
-
#validate(params, **context) ⇒ Object
Checks if the operation is valid to call in the current context and parameters.
Constructor Details
#initialize(operation, policy: UNDEFINED, policies: [UNDEFINED], precondition: nil, preconditions: [], after: [], **options) ⇒ Command
Returns a new instance of Command.
196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/operations/command.rb', line 196 def initialize( operation, policy: UNDEFINED, policies: [UNDEFINED], precondition: nil, preconditions: [], after: [], ** ) policies_sum = Array.wrap(policy) + policies result_policies = policies_sum - [UNDEFINED] unless policies_sum == [UNDEFINED, UNDEFINED] [:policies] = result_policies if result_policies preconditions.push(precondition) if precondition.present? super(operation, preconditions: preconditions, on_success: after, **) end |
Class Method Details
.build(operation, contract = nil, **deps) ⇒ Object
A short-cut to initialize operation by convention:
Namespace::OperationName - operation Namespace::OperationName::Contract - contract Namespace::OperationName::Policies - policies Namespace::OperationName::Preconditions - preconditions
All the dependencies are passed to every component’s initializer, so they’d be better tolerant to unknown dependencies. Luckily it is easily achievable with Dry::Initializer. This plays really well with Operations::Convenience
186 187 188 189 190 191 192 193 194 |
# File 'lib/operations/command.rb', line 186 def self.build(operation, contract = nil, **deps) = { contract: (contract || operation::Contract).new(**deps), policies: [operation::Policy.new(**deps)] } [:preconditions] = [operation::Precondition.new(**deps)] if operation.const_defined?(:Precondition) new(operation.new(**deps), **) end |
Instance Method Details
#allowed(params = EMPTY_HASH, **context) ⇒ Object
Works the same way as callable but checks only the policy.
255 256 257 |
# File 'lib/operations/command.rb', line 255 def allowed(params = EMPTY_HASH, **context) operation_result(component(:policies).call(params.to_h, context)) end |
#as_json ⇒ Object
293 294 295 296 297 298 299 |
# File 'lib/operations/command.rb', line 293 def as_json(*) { **main_components_as_json, **form_components_as_json, configuration: configuration.as_json } end |
#call(params, **context) ⇒ Object
Executes all the components in a particular order. Returns the result on any step failure. First it validates the user input with the contract then it checks the policy and preconditions and if everything passes - executes the operation routine. The whole process always happens inside of a DB transaction.
219 220 221 |
# File 'lib/operations/command.rb', line 219 def call(params, **context) operation_result(unwrap_monad(call_monad(params.to_h, context))) end |
#call!(params, **context) ⇒ Object
Works the same way as call but raises an exception on operation failure.
224 225 226 227 228 229 |
# File 'lib/operations/command.rb', line 224 def call!(params, **context) result = call(params, **context) raise OperationFailed.new(result) if result.failure? result end |
#callable(params = EMPTY_HASH, **context) ⇒ Object
Checks if the operation is possible to call in the current context. Performs both: policy and preconditions checks.
250 251 252 |
# File 'lib/operations/command.rb', line 250 def callable(params = EMPTY_HASH, **context) operation_result(unwrap_monad(callable_monad(component(:contract).call(params.to_h, context)))) end |
#merge(**changes) ⇒ Object
Instantiates a new command with the given fields updated. Useful for defining multiple commands for a single operation body.
210 211 212 |
# File 'lib/operations/command.rb', line 210 def merge(**changes) self.class.new(operation, **self.class.dry_initializer.attributes(self), **changes) end |
#possible(params = EMPTY_HASH, **context) ⇒ Object
Works the same way as callable but checks only preconditions.
260 261 262 |
# File 'lib/operations/command.rb', line 260 def possible(params = EMPTY_HASH, **context) operation_result(component(:preconditions).call(params.to_h, context)) end |
#pretty_print(pp) ⇒ Object
278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/operations/command.rb', line 278 def pretty_print(pp) attributes = self.class.dry_initializer.attributes(self) pp.object_group(self) do pp.seplist(attributes.keys, -> { pp.text "," }) do |name| pp.breakable " " pp.group(1) do pp.text name.to_s pp.text " = " pp.pp send(name) end end end end |
#try_call!(params, **context) ⇒ Object
Calls the operation and raises an exception in case of a failure but only if preconditions and policies have passed. This means that the exception will be raised only on contract or the operation body failure.
235 236 237 238 239 240 |
# File 'lib/operations/command.rb', line 235 def try_call!(params, **context) result = call(params, **context) raise OperationFailed.new(result) if result.failure? && !result.failed_precheck? result end |
#valid?(*args, **kwargs) ⇒ Boolean
Returns boolean result instead of Operations::Result for validate method. True on success and false on failure.
274 275 276 |
# File 'lib/operations/command.rb', line 274 def valid?(*args, **kwargs) validate(*args, **kwargs).success? end |
#validate(params, **context) ⇒ Object
Checks if the operation is valid to call in the current context and parameters. Performs policy preconditions and contract checks.
244 245 246 |
# File 'lib/operations/command.rb', line 244 def validate(params, **context) operation_result(unwrap_monad(validate_monad(params.to_h, context))) end |