Class: GLCommand::Callable
- Inherits:
-
Object
- Object
- GLCommand::Callable
- Includes:
- Validatable
- Defined in:
- lib/gl_command/callable.rb
Direct Known Subclasses
Constant Summary collapse
- DEFAULT_OPTS =
{ raise_errors: false, skip_unknown_parameters: true, in_chain: false }.freeze
- RESERVED_WORDS =
(DEFAULT_OPTS.keys + GLCommand::ChainableContext.reserved_words).sort.freeze
Instance Attribute Summary collapse
-
#context ⇒ Object
readonly
Returns the value of attribute context.
Class Method Summary collapse
- .allows(*attributes, **strong_attributes) ⇒ Object
-
.arguments ⇒ Object
arguments are what’s passed to the .call command (the allows and requires).
-
.arguments_and_returns ⇒ Object
arguments_and_returns is just the keys (names) of the arguments and returns.
-
.build_context(raise_errors: false, skip_unknown_parameters: false, error: nil, **arguments_and_returns) ⇒ Object
error can be passed to build context, useful for stubbing in tests.
-
.call(*posargs, **args) ⇒ Object
Make raise_errors and skip_unknown_parameters reserved and raise if they’re passed in.
- .call!(*posargs, **args) ⇒ Object
-
.chain? ⇒ Boolean
Used internally by GLCommand (probably don’t reference in your own GLCommands) is true in GLCommand::Chainable.
- .error_handlers ⇒ Object
- .requires(*attributes, **strong_attributes) ⇒ Object
- .rescue_from(error_class, with:) ⇒ Object
- .returns(*attributes, **strong_attributes) ⇒ Object
Instance Method Summary collapse
-
#call ⇒ Object
Ensure that call is overridden in subclass.
-
#initialize(context = nil) ⇒ Callable
constructor
A new instance of Callable.
- #perform_call(args) ⇒ Object
-
#rollback ⇒ Object
define a rollback method if you want to have actions for rolling back it is called in handle_failure.
- #stop_and_fail!(passed_error = nil, no_notify: false) ⇒ Object
Methods included from Validatable
#validatable_valid?, #validate_validatable!
Constructor Details
#initialize(context = nil) ⇒ Callable
Returns a new instance of Callable.
108 109 110 |
# File 'lib/gl_command/callable.rb', line 108 def initialize(context = nil) @context = context end |
Instance Attribute Details
#context ⇒ Object (readonly)
Returns the value of attribute context.
106 107 108 |
# File 'lib/gl_command/callable.rb', line 106 def context @context end |
Class Method Details
.allows(*attributes, **strong_attributes) ⇒ Object
51 52 53 |
# File 'lib/gl_command/callable.rb', line 51 def allows(*attributes, **strong_attributes) @allows ||= strong_args_hash(*attributes, **strong_attributes).freeze end |
.arguments ⇒ Object
arguments are what’s passed to the .call command (the allows and requires)
61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/gl_command/callable.rb', line 61 def arguments return @arguments if defined?(@arguments) duplicated_keys = requires.keys & allows.keys raise "Duplicated: #{duplicated_keys} - in both requires and allows" if duplicated_keys.any? @arguments = (requires.keys + allows.keys).freeze delegate(*@arguments + returns, to: :context) @arguments end |
.arguments_and_returns ⇒ Object
arguments_and_returns is just the keys (names) of the arguments and returns
74 75 76 |
# File 'lib/gl_command/callable.rb', line 74 def arguments_and_returns (arguments + returns).uniq end |
.build_context(raise_errors: false, skip_unknown_parameters: false, error: nil, **arguments_and_returns) ⇒ Object
error can be passed to build context, useful for stubbing in tests
39 40 41 42 43 44 45 |
# File 'lib/gl_command/callable.rb', line 39 def build_context(raise_errors: false, skip_unknown_parameters: false, error: nil, **arguments_and_returns) new_context = context_class.new(self, raise_errors:, skip_unknown_parameters:, **arguments_and_returns) new_context.error = error if error.present? new_context end |
.call(*posargs, **args) ⇒ Object
Make raise_errors and skip_unknown_parameters reserved and raise if they’re passed in
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/gl_command/callable.rb', line 14 def call(*posargs, **args) if arguments_and_returns.intersect?(RESERVED_WORDS) raise ArgumentError, "You used reserved word(s): #{arguments_and_returns & RESERVED_WORDS}\n" \ '(check GLCommand::Callable::RESERVED_WORDS for the full list)' end if posargs.any? raise ArgumentError, "`call` only supports keyword args, not positional - you passed: '#{posargs}'" end # DEFAULT_OPTS contains skip_unknown_parameters: true - so it raises on call # (rather than in context initialize) to make errors more legible opts = DEFAULT_OPTS.merge(raise_errors: args.delete(:raise_errors), in_chain: args.delete(:in_chain)).compact # args are passed in in perform_call(args) so that invalid args raise in a legible place new(build_context(**args.merge(opts))).perform_call(args) end |
.call!(*posargs, **args) ⇒ Object
34 35 36 |
# File 'lib/gl_command/callable.rb', line 34 def call!(*posargs, **args) call(*posargs, **args.merge(raise_errors: true)) end |
.chain? ⇒ Boolean
Used internally by GLCommand (probably don’t reference in your own GLCommands) is true in GLCommand::Chainable
80 81 82 |
# File 'lib/gl_command/callable.rb', line 80 def chain? false end |
.error_handlers ⇒ Object
88 89 90 |
# File 'lib/gl_command/callable.rb', line 88 def error_handlers @error_handlers ||= {} end |
.requires(*attributes, **strong_attributes) ⇒ Object
47 48 49 |
# File 'lib/gl_command/callable.rb', line 47 def requires(*attributes, **strong_attributes) @requires ||= strong_args_hash(*attributes, **strong_attributes).freeze end |
.rescue_from(error_class, with:) ⇒ Object
84 85 86 |
# File 'lib/gl_command/callable.rb', line 84 def rescue_from(error_class, with:) error_handlers[error_class] = with end |
.returns(*attributes, **strong_attributes) ⇒ Object
55 56 57 58 |
# File 'lib/gl_command/callable.rb', line 55 def returns(*attributes, **strong_attributes) # NOTE: Because returns aren't validated, we don't store the types (only store keys) @returns ||= strong_args_hash(*attributes, **strong_attributes).keys.freeze end |
Instance Method Details
#call ⇒ Object
Ensure that call is overridden in subclass
137 138 139 |
# File 'lib/gl_command/callable.rb', line 137 def call raise 'You must define the `call` instance method on your GLCommand' end |
#perform_call(args) ⇒ Object
112 113 114 115 116 117 118 119 120 121 |
# File 'lib/gl_command/callable.rb', line 112 def perform_call(args) raise_for_invalid_args!(**args) instrument_command(:before_call) call_with_callbacks instrument_command(:after_call) raise_unless_chained_or_skipped if self.class.chain? # defined in GLCommand::Chainable context.failure? ? handle_failure : context rescue StandardError => e handle_failure(e) end |
#rollback ⇒ Object
define a rollback method if you want to have actions for rolling back it is called in handle_failure
134 |
# File 'lib/gl_command/callable.rb', line 134 def rollback; end |
#stop_and_fail!(passed_error = nil, no_notify: false) ⇒ Object
123 124 125 126 127 128 129 130 |
# File 'lib/gl_command/callable.rb', line 123 def stop_and_fail!(passed_error = nil, no_notify: false) # manually setting instance_variable because @no_notify shouldn't be updated in commands # (e.g. context shouldn't have an attr_writer) context.instance_variable_set(:@no_notify, no_notify) context.error = passed_error raise context.no_notifiable_error_to_raise # See comment in #handle_failure end |