Class: Fluxo::Operation

Inherits:
Object
  • Object
show all
Includes:
ActiveModelExtension, Attributes
Defined in:
lib/fluxo/operation.rb,
lib/fluxo/operation/attributes.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

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ActiveModelExtension

included

Methods included from Attributes

included

Class Method Details

.call(**attrs) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/fluxo/operation.rb', line 16

def call(**attrs)
  instance = new

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

.flow(*methods) ⇒ Object



12
13
14
# File 'lib/fluxo/operation.rb', line 12

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

Instance Method Details

#__execute_flow__(steps: [], attributes: {}, validate: true) ⇒ 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.



39
40
41
42
43
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
# File 'lib/fluxo/operation.rb', line 39

def __execute_flow__(steps: [], attributes: {}, validate: true)
  transient_attributes, transient_ids = attributes.dup, Hash.new { |h, k| h[k] = [] }

  result = nil
  steps.unshift(:__validate_required_attributes__) if self.class.required_attributes.any? && validate
  steps.unshift(:__validate__) if self.class.validations_proxy && validate
  steps.each_with_index do |step, idx|
    if step.is_a?(Hash)
      group_result = step.each do |group_method, group_steps|
        send(group_method, **transient_attributes) do |group_attrs|
          result = __execute_flow__(validate: false, steps: group_steps, attributes: (group_attrs || transient_attributes))
        end
        result = group_result if group_result.is_a?(Fluxo::Result)
        break unless result.success?
        transient_attributes = result.transient_attributes # Update transient attributes with the group result in case of value is not a Hash
      end
    else
      result = __wrap_result__(send(step, **transient_attributes))
      transient_ids[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
    result.mutate(transient_attributes: transient_attributes)
  end
  result.mutate(ids: transient_ids[result.type].uniq, operation: self)
end

#call!Object

Raises:

  • (NotImplementedError)


30
31
32
33
34
35
# File 'lib/fluxo/operation.rb', line 30

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



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

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



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

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



98
99
100
# File 'lib/fluxo/operation.rb', line 98

def Void
  Success(:void) { nil }
end