Class: Rails::UseCase

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Validations, Callable
Defined in:
lib/rails/use_case.rb,
lib/rails/use_case/outcome.rb

Overview

UseCase. See README.

Defined Under Namespace

Classes: Error, Outcome

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.stepsObject (readonly)

Returns the value of attribute steps.



17
18
19
# File 'lib/rails/use_case.rb', line 17

def steps
  @steps
end

Instance Attribute Details

#recordObject (readonly)

Returns the value of attribute record.



12
13
14
# File 'lib/rails/use_case.rb', line 12

def record
  @record
end

Class Method Details

.failure(code = nil, options = {}) ⇒ Object



57
58
59
60
# File 'lib/rails/use_case.rb', line 57

def self.failure(code = nil, options = {})
  options[:code] = code || options[:code] || :failure
  step :failure, options
end

.record(param = nil, &block) ⇒ Object

DSL to set the record source.



73
74
75
76
77
# File 'lib/rails/use_case.rb', line 73

def self.record(param = nil, &block)
  block = -> { send(param.to_sym) } unless block_given?

  define_method(:determine_record, &block)
end

.step(name = :inline, options = {}, &block) ⇒ Object

DSL to define a process step of the UseCase. You can use if/unless with a lambda in the options to conditionally skip the step.



40
41
42
43
44
45
46
47
48
49
# File 'lib/rails/use_case.rb', line 40

def self.step(name = :inline, options = {}, &block)
  @steps ||= []

  if block_given?
    options[:do] = block
    name = :inline
  end

  @steps << { name: name.to_sym, options: options }
end

.success(options = {}) ⇒ Object



52
53
54
# File 'lib/rails/use_case.rb', line 52

def self.success(options = {})
  step :success, options
end

.with(mod) ⇒ Object

DSL to include a behavior.



65
66
67
# File 'lib/rails/use_case.rb', line 65

def self.with(mod)
  include mod
end

Instance Method Details

#break_when_invalid!Object



145
146
147
148
149
# File 'lib/rails/use_case.rb', line 145

def break_when_invalid!
  return true if valid?

  fail! code: :validation_failed, message: errors.full_messages.join(', ')
end

#call(params) ⇒ Object

Will be called by Callable.call.



24
25
26
27
28
29
30
31
# File 'lib/rails/use_case.rb', line 24

def call(params)
  prepare params
  process

  successful_outcome
rescue UseCase::Error => e
  failure_outcome e
end

#fail!(code: nil, message: 'Failed') ⇒ Object

Raises:



109
110
111
112
# File 'lib/rails/use_case.rb', line 109

def fail!(code: nil, message: 'Failed')
  @error_code = code
  raise UseCase::Error, message
end

#prepare(params) ⇒ Object

Prepare step. Runs automatically before the UseCase process starts. Sets all params as instance variables and then runs the validations.



135
136
137
138
139
140
141
# File 'lib/rails/use_case.rb', line 135

def prepare(params)
  params.each do |key, value|
    instance_variable_set "@#{key}", value
  end

  break_when_invalid!
end

#processObject

Will run the steps of the use case.



81
82
83
84
# File 'lib/rails/use_case.rb', line 81

def process
  @record = determine_record if respond_to?(:determine_record)
  run_steps
end

#run_stepsObject



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/rails/use_case.rb', line 87

def run_steps
  self.class.steps.each do |step|
    # Check wether to skip when :if or :unless are set.
    next if skip_step?(step)

    opts = step[:options]
    name = step[:name]

    # Handle failure and success steps.
    return true if name == :success

    fail!(code: opts[:code], message: opts[:message]) if name == :failure

    # Run the lambda, when :do is set. Otherwise call the method.
    next if opts[:do] ? instance_eval(&opts[:do]) : send(name)

    # result is false, so we have a failure.
    fail! code: :step_false, message: "Step '#{name}' returned false"
  end
end

#skip_step?(step) ⇒ Boolean

Checks whether to skip a step.



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/rails/use_case.rb', line 117

def skip_step?(step)
  if step[:options][:if]
    proc = step[:options][:if]
    result = instance_exec(&proc)
    return true unless result
  end

  return false unless step[:options][:unless]

  proc = step[:options][:unless]
  result = instance_exec(&proc)
  return true if result
end