Class: StepperMotor::Step
- Inherits:
-
Object
- Object
- StepperMotor::Step
- Defined in:
- lib/stepper_motor/step.rb
Overview
Describes a step in a journey. These objects get stored inside the step_definitions
array of the Journey subclass. When the step gets performed, the block passed to the
constructor will be instance_exec'd with the Journey model being the context
Defined Under Namespace
Classes: MissingDefinition
Instance Attribute Summary collapse
-
#name ⇒ String
readonly
The name of the step or method to call on the Journey.
-
#wait ⇒ Numeric, ActiveSupport::Duration
readonly
How long to wait before performing the step.
Instance Method Summary collapse
-
#initialize(name:, on_exception: :pause!, wait: 0, skip_if: false, &step_block) ⇒ Step
constructor
Creates a new step definition.
-
#perform_in_context_of(journey) ⇒ Object
Performs the step on the passed Journey, wrapping the step with the required context.
-
#should_skip?(journey) ⇒ Boolean
Checks if the step should be skipped based on the skip_if condition.
Constructor Details
#initialize(name:, on_exception: :pause!, wait: 0, skip_if: false, &step_block) ⇒ Step
Creates a new step definition
30 31 32 33 34 35 36 |
# File 'lib/stepper_motor/step.rb', line 30 def initialize(name:, on_exception: :pause!, wait: 0, skip_if: false, &step_block) @step_block = step_block @name = name.to_s @wait = wait @on_exception = on_exception # TODO: Validate? @skip_if_condition = StepperMotor::Conditional.new(skip_if) end |
Instance Attribute Details
#name ⇒ String (readonly)
Returns the name of the step or method to call on the Journey.
11 12 13 |
# File 'lib/stepper_motor/step.rb', line 11 def name @name end |
#wait ⇒ Numeric, ActiveSupport::Duration (readonly)
Returns how long to wait before performing the step.
14 15 16 |
# File 'lib/stepper_motor/step.rb', line 14 def wait @wait end |
Instance Method Details
#perform_in_context_of(journey) ⇒ Object
Performs the step on the passed Journey, wrapping the step with the required context.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/stepper_motor/step.rb', line 53 def perform_in_context_of(journey) # Return early should the `skip_if` condition be truthy if should_skip?(journey) journey.logger.info { "skipping as skip_if: condition was truthy" } return end # This is a tricky bit. # # reattempt!, cancel! (and potentially - future flow control methods) all use `throw` to # immediately hop out of the perform block. They all use the same symbol thrown - :abort_step. # Nothing after `reattempt!` and `cancel!` in the same scope will run because of that `throw` - # not even the `rescue` clauses, so we need to catch here instead of the `perform_next_step!` # method. This way, if the step raises an exception, we can still let Journey flow control methods # be used, but we can capture the exception. Moreover: we need to be able to _call_ those methods from # within the rescue() clauses. So: catch(:abort_step) do if @step_block journey.instance_exec(&@step_block) elsif journey.respond_to?(name) journey.public_send(name) # TODO: context/params? else raise MissingDefinition.new(<<~MSG, name, _args = nil, _private = false, receiver: journey) No block or method to use for step `#{name}' on #{journey.class} MSG end end rescue MissingDefinition # This journey won't succeed with any number of reattempts, pause it. catch(:abort_step) { journey.pause! } raise rescue => e # Act according to the set policy. The basic 2 for the moment are :reattempt! and :cancel!, # and can be applied by just calling the methods on the passed journey case @on_exception when :reattempt!, :cancel!, :pause!, :skip! catch(:abort_step) { journey.public_send(@on_exception) } else # Leave the journey hanging in the "performing" state journey.logger.warn { "unusual on_exception: value (#{@on_exception.inspect}) - the journey will be left hanging in 'performing' state and will be collected as hung" } end # Re-raise the exception so that the Rails error handling can register it raise e end |
#should_skip?(journey) ⇒ Boolean
Checks if the step should be skipped based on the skip_if condition
42 43 44 |
# File 'lib/stepper_motor/step.rb', line 42 def should_skip?(journey) @skip_if_condition.satisfied_by?(journey) end |