module ActionOperation

Constants

Catch
Drift
State
Task
VERSION

Public Class Methods

new(raw:) click to toggle source
# File lib/action_operation.rb, line 17
def initialize(raw:)
  raise ArgumentError, "needs to be a Hash" unless raw.kind_of?(Hash)

  @raw = raw
end

Public Instance Methods

around_catch(exception:, raw:, step:, &callback) click to toggle source
# File lib/action_operation.rb, line 127
def around_catch(exception:, raw:, step:, &callback)
  callback.call(exception: exception, raw: raw, step: step)
end
around_catches(exception:, raw:, &callback) click to toggle source
# File lib/action_operation.rb, line 123
def around_catches(exception:, raw:, &callback)
  callback.call(exception: exception, raw: raw)
end
around_step(state: nil, exception: nil, raw:, step:, &callback) click to toggle source
# File lib/action_operation.rb, line 111
def around_step(state: nil, exception: nil, raw:, step:, &callback)
  callback.call(state: state, exception: exception, raw: raw, step: step)
end
around_steps(raw:, &callback) click to toggle source
# File lib/action_operation.rb, line 107
def around_steps(raw:, &callback)
  callback.call(raw: raw)
end
around_task(state:, raw:, step:, &callback) click to toggle source
# File lib/action_operation.rb, line 119
def around_task(state:, raw:, step:, &callback)
  callback.call(state: state, raw: raw, step: step)
end
around_tasks(raw:, &callback) click to toggle source
# File lib/action_operation.rb, line 115
def around_tasks(raw:, &callback)
  callback.call(raw: raw)
end
call(start: nil, raw: @raw) click to toggle source
# File lib/action_operation.rb, line 23
def call(start: nil, raw: @raw)
  around_steps(raw: raw) do
    begin
      around_tasks(raw: raw) do
        tasks(start, raw)
      end
    rescue *left.select(&:exception).map(&:exception).uniq => handled_exception
      around_catches(exception: handled_exception, raw: raw) do
        catches(handled_exception, raw)
      end
    end
  end
end
catch(name, exception: StandardError) click to toggle source
# File lib/action_operation.rb, line 160
def catch(name, exception: StandardError)
  left << Catch.new(name, self, exception)
end
drift(to:) click to toggle source
# File lib/action_operation.rb, line 101
def drift(to:)
  raise ArgumentError, "needs to be a Symbol or String" unless to.kind_of?(Symbol) || to.kind_of?(String)

  Drift.new(to)
end
fresh(state:) click to toggle source
# File lib/action_operation.rb, line 95
def fresh(state:)
  raise ArgumentError, "needs to be a Hash" unless state.kind_of?(Hash)

  State.new(state)
end
reraise(exception:, **) click to toggle source
# File lib/action_operation.rb, line 139
def reraise(exception:, **)
  raise exception
end
schema(name, &structure) click to toggle source
# File lib/action_operation.rb, line 148
def schema(name, &structure)
  schemas[name] = Class.new do
    include(SmartParams)

    schema type: SmartParams::Strict::Hash, &structure
  end
end
schemas() click to toggle source
# File lib/action_operation.rb, line 172
def schemas
  @schemas ||= Hash.new
end
task(name, required: true) click to toggle source
# File lib/action_operation.rb, line 156
def task(name, required: true)
  right << Task.new(name, self, required)
end

Private Instance Methods

catches(exception, raw) click to toggle source
# File lib/action_operation.rb, line 68
        def catches(exception, raw)
  left.select do |failure|
    failure.exception === exception
  end.reduce(exception) do |exception, step|
    raise Error::MissingError, step: step unless respond_to?(step.name)

    # puts "#{step.class}::#{step.receiver}##{step.name}"

    begin
      value = around_step(exception: exception, raw: raw, step: step) do
        around_catch(exception: exception, raw: raw, step: step) do
          public_send(step.name, exception: exception, state: raw, step: @latest_step)
        end
      end
      # puts "#{step.class}::#{step.receiver}##{step.name} #{value}"
    rescue SmartParams::Error::InvalidPropertyType => invalid_property_type_exception
      raise Error::StepSchemaMismatch, step: @latest_step, schema: self.class.schemas.fetch(@latest_step.name), raw: raw, cause: invalid_property_type_exception
    end

    if value.kind_of?(Drift)
      break call(start: right.find_index { |step| step.name == value.to }, raw: raw)
    else
      exception
    end
  end
end
left() click to toggle source
# File lib/action_operation.rb, line 131
        def left
  self.class.left
end
right() click to toggle source
# File lib/action_operation.rb, line 135
        def right
  self.class.right
end
tasks(start, raw) click to toggle source
# File lib/action_operation.rb, line 37
        def tasks(start, raw)
  right.from(start || 0).reduce(raw) do |state, step|
    next state unless step.required || (start && right.at(start) == step)

    raise Error::MissingTask, step: step unless respond_to?(step.name)
    raise Error::MissingSchema, step: step unless self.class.schemas.key?(step.name)

    # NOTE: We only care about this so we can reference it in the rescue
    @latest_step = step

    # puts "#{step.class}::#{step.receiver}##{step.name}"

    begin
      value = around_step(state: self.class.schemas.fetch(step.name).new(state), raw: raw, step: step) do
        around_task(state: self.class.schemas.fetch(step.name).new(state), raw: raw, step: step) do
          public_send(step.name, state: self.class.schemas.fetch(step.name).new(state))
        end
      end
      # puts "#{step.class}::#{step.receiver}##{step.name} #{value}"
    rescue SmartParams::Error::InvalidPropertyType => invalid_property_type_exception
      raise Error::StepSchemaMismatch, step: step, schema: self.class.schemas.fetch(step.name), raw: raw, cause: invalid_property_type_exception
    end

    case value
      when State then value.raw
      when Drift then break call(start: right.find_index { |step| step.name == value.to }, raw: state)
      else state
    end
  end
end