Class: Fluxo::Operation

Inherits:
Object
  • Object
show all
Includes:
ActiveModelExtension, Attributes, Constructor
Defined in:
lib/fluxo/operation.rb,
lib/fluxo/operation/attributes.rb,
lib/fluxo/operation/constructor.rb,
lib/fluxo/active_model_extension.rb

Overview

I know that the underline instance method name is not the best, but I don’t want to conflict with the Operation step methods that are going to inherit this class.

Defined Under Namespace

Modules: Attributes, Constructor

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ActiveModelExtension

included

Methods included from Constructor

included

Methods included from Attributes

included

Class Method Details

.call(**attrs) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/fluxo/operation.rb', line 20

def call(**attrs)
  instance = new

  begin
    instance.__execute_flow__(steps: [:call!], attributes: attrs)
  rescue InvalidResultError, AttributeError, ValidationDefinitionError => e
    raise e
  rescue => e
    Fluxo::Result.new(type: :exception, value: e, operation: instance, ids: %i[error]).tap do |result|
      Fluxo.config.error_handlers.each { |handler| handler.call(result) }
    end
  end
end

.flow(*methods) ⇒ Object



16
17
18
# File 'lib/fluxo/operation.rb', line 16

def flow(*methods)
  define_method(:call!) { |**attrs| __execute_flow__(steps: methods, attributes: attrs) }
end

Instance Method Details

#__execute_flow__(steps: [], attributes: {}) ⇒ Object

Calls step-method by step-method always passing the value to the next step If one of the methods is a failure stop the execution and return a result.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/fluxo/operation.rb', line 44

def __execute_flow__(steps: [], attributes: {})
  transient_attributes, transient_ids = attributes.dup, {ok: [], failure: [], exception: []}
  __validate_attributes__(first_step: steps.first, attributes: transient_attributes)

  result = nil
  steps.unshift(:__validate__) if self.class.validations_proxy # add validate step before the first step
  steps.each_with_index do |step, idx|
    if step.is_a?(Hash)
      step.each do |group_method, group_steps|
        send(group_method, **transient_attributes) do |group_attrs|
          result = __execute_flow__(steps: group_steps, attributes: (group_attrs || transient_attributes))
        end
        break unless result.success?
      end
    else
      result = __wrap_result__(send(step, **transient_attributes))
      transient_ids.fetch(result.type).push(*result.ids)
    end

    break unless result.success?

    if steps[idx + 1]
      transient_attributes = __merge_result_attributes__(
        new_attributes: result.value,
        old_attributes: transient_attributes,
        next_step: steps[idx + 1]
      )
    end
  end
  result.tap { |r| r.ids = transient_ids.fetch(r.type).uniq }
end

#call!Object

Raises:

  • (NotImplementedError)


35
36
37
38
39
40
# File 'lib/fluxo/operation.rb', line 35

def call!(**)
  raise NotImplementedError, <<~ERROR
    You must implement the #call! method in your operation.
    For complexes operations, you can use the #flow method instead.
  ERROR
end

#Failure(value_or_result_id = nil) ⇒ Object

Parameters:

  • value_or_result_id (Any) (defaults to: nil)

    The value for the result or the id when the result comes from block



89
90
91
92
93
94
95
96
97
98
# File 'lib/fluxo/operation.rb', line 89

def Failure(value_or_result_id = nil)
  attrs = {type: :failure, operation: self}
  if block_given?
    attrs[:ids] = value_or_result_id
    attrs[:value] = yield
  else
    attrs[:value] = value_or_result_id
  end
  Fluxo::Result.new(**attrs)
end

#Success(value_or_result_id = nil) ⇒ Object

Parameters:

  • value_or_result_id (Any) (defaults to: nil)

    The value for the result or the id when the result comes from block



77
78
79
80
81
82
83
84
85
86
# File 'lib/fluxo/operation.rb', line 77

def Success(value_or_result_id = nil)
  attrs = {type: :ok, operation: self}
  if block_given?
    attrs[:ids] = value_or_result_id
    attrs[:value] = yield
  else
    attrs[:value] = value_or_result_id
  end
  Fluxo::Result.new(**attrs)
end

#VoidObject



100
101
102
# File 'lib/fluxo/operation.rb', line 100

def Void
  Success(:void) { nil }
end