Class: CallSheet::Transaction

Inherits:
Object
  • Object
show all
Defined in:
lib/call_sheet/transaction.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(steps) ⇒ Transaction

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Transaction.



9
10
11
# File 'lib/call_sheet/transaction.rb', line 9

def initialize(steps)
  @steps = steps
end

Instance Attribute Details

#stepsObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



6
7
8
# File 'lib/call_sheet/transaction.rb', line 6

def steps
  @steps
end

Instance Method Details

#append(other = nil, **options, &block) ⇒ CallSheet::Transaction

Return a transaction with the steps from the provided transaction appended onto the end of the steps in self.

Examples:

Append an existing transaction

my_transaction = CallSheet(container: container) do
  step :first
  step :second
end

other_transaction = CallSheet(container: container) do
  step :another
end

my_transaction.append(other_transaction)

Append a transaction defined inline

my_transaction = CallSheet(container: container) do
  step :first
  step :second
end

my_transaction.append(container: container) do
  step :another
end

Parameters:

  • other (CallSheet::Transaction) (defaults to: nil)

    the transaction to append. Optional if you will define a transaction inline via a block.

  • options (Hash)

    the options hash for defining a transaction inline via a block. Optional if the transaction is passed directly as other.

Options Hash (**options):

  • :container (#[])

    the operations container

Returns:



173
174
175
176
177
# File 'lib/call_sheet/transaction.rb', line 173

def append(other = nil, **options, &block)
  other = accept_or_build_transaction(other, **options, &block)

  self.class.new(steps + other.steps)
end

#call(input, options = {}, &block) ⇒ Right, Left Also known as: []

Run the transaction.

Each operation will be called in the order it was specified, with its output passed as input to the next operation. Operations will only be called if the previous step was a success.

If any of the operations require extra arguments beyond the main input e.g. with a signature like ‘#call(something_else, input)`, then you must pass the extra arguments as arrays for each step in the options hash.

The return value will be the output from the last operation, wrapped in a [Kleisli](kleisli) Either object, a Right for a successful transaction or a Left for a failed transaction.

[kleisli]: rubygems.org/gems/kleisli

Examples:

Running a transaction

my_transaction.call(some_input)

Running a transaction with extra step arguments

my_transaction.call(some_input, step_name: [extra_argument])

Parameters:

  • input
  • options (Hash) (defaults to: {})

    extra step arguments

Returns:

  • (Right, Left)

    output from the final step



41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/call_sheet/transaction.rb', line 41

def call(input, options = {}, &block)
  assert_valid_options(options)
  assert_options_satisfy_step_arity(options)

  steps = steps_with_options_applied(options)
  result = steps.inject(Right(input), :>>)

  if block
    block.call(ResultMatcher.new(result))
  else
    result
  end
end

#insert(other = nil, before: nil, after: nil, **options, &block) ⇒ CallSheet::Transaction

Return a transaction with the steps from the provided transaction inserted into a specific place among the steps in self.

Transactions can be inserted either before or after a named step.

Examples:

Insert an existing transaction (before a step)

my_transaction = CallSheet(container: container) do
  step :first
  step :second
end

other_transaction = CallSheet(container: container) do
  step :another
end

my_transaction.insert(other_transaction, before: :second)

Append a transaction defined inline (after a step)

my_transaction = CallSheet(container: container) do
  step :first
  step :second
end

my_transaction.insert(after: :first, container: container) do
  step :another
end

Parameters:

  • other (CallSheet::Transaction) (defaults to: nil)

    the transaction to append. Optional if you will define a transaction inline via a block.

  • before (Symbol) (defaults to: nil)

    the name of the step before which the transaction should be inserted (provide either this or after)

  • after (Symbol) (defaults to: nil)

    the name of the step after which the transaction should be inserted (provide either this or before)

  • options (Hash)

    the options hash for defining a transaction inline via a block. Optional if the transaction is passed directly as other.

Options Hash (**options):

  • :container (#[])

    the operations container

Returns:



220
221
222
223
224
225
226
227
228
229
230
# File 'lib/call_sheet/transaction.rb', line 220

def insert(other = nil, before: nil, after: nil, **options, &block)
  insertion_step = before || after
  unless steps.map(&:step_name).include?(insertion_step)
    raise ArgumentError, "+#{insertion_step}+ is not a valid step name"
  end

  other = accept_or_build_transaction(other, **options, &block)
  index = steps.index { |step| step.step_name == insertion_step } + (!!after ? 1 : 0)

  self.class.new(steps.dup.insert(index, *other.steps))
end

#prepend(other = nil, **options, &block) ⇒ CallSheet::Transaction

Return a transaction with the steps from the provided transaction prepended onto the beginning of the steps in self.

Examples:

Prepend an existing transaction

my_transaction = CallSheet(container: container) do
  step :first
  step :second
end

other_transaction = CallSheet(container: container) do
  step :another
end

my_transaction.prepend(other_transaction)

Prepend a transaction defined inline

my_transaction = CallSheet(container: container) do
  step :first
  step :second
end

my_transaction.prepend(container: container) do
  step :another
end

Parameters:

  • other (CallSheet::Transaction) (defaults to: nil)

    the transaction to prepend. Optional if you will define a transaction inline via a block.

  • options (Hash)

    the options hash for defining a transaction inline via a block. Optional if the transaction is passed directly as other.

Options Hash (**options):

  • :container (#[])

    the operations container

Returns:



132
133
134
135
136
# File 'lib/call_sheet/transaction.rb', line 132

def prepend(other = nil, **options, &block)
  other = accept_or_build_transaction(other, **options, &block)

  self.class.new(other.steps + steps)
end

#remove(step, ...) ⇒ CallSheet::Transaction

Return a transaction with steps removed.

Examples:

my_transaction = CallSheet(container: container) do
  step :first
  step :second
  step :third
end

my_transaction.remove(:first, :third)

Parameters:

  • step (Symbol)

    the names of a step to remove

  • ... (Symbol)

    more names of steps to remove

Returns:



250
251
252
# File 'lib/call_sheet/transaction.rb', line 250

def remove(*steps_to_remove)
  self.class.new(steps.reject { |step| steps_to_remove.include?(step.step_name) })
end

#subscribe(listeners) ⇒ Object

Subscribe to notifications from steps.

When each step completes, it will send a [step_name]_success or [step_name]_failure message to any subscribers.

For example, if you had a step called persist, then it would send either persist_success or persist_failure messages to subscribers after the operation completes.

Pass a single object to subscribe to notifications from all steps, or pass a hash with step names as keys to subscribe to notifications from specific steps.

Notifications are implemented using the [Wisper](wisper) gem.

[wisper]: rubygems.org/gems/wisper

Examples:

Subscribing to notifications from all steps

my_transaction.subscribe(my_listener)

Subscribing to notifications from specific steps

my_transaction.subscirbe(some_step: my_listener, another_step: another_listener)

Parameters:

  • listeners (Object, Hash{Symbol => Object})

    the listener object or hash of steps and listeners



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/call_sheet/transaction.rb', line 83

def subscribe(listeners)
  if listeners.is_a?(Hash)
    listeners.each do |step_name, listener|
      steps.detect { |step| step.step_name == step_name }.subscribe(listener)
    end
  else
    steps.each do |step|
      step.subscribe(listeners)
    end
  end

  self
end