-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathprocess.rb
More file actions
145 lines (106 loc) · 3.5 KB
/
process.rb
File metadata and controls
145 lines (106 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# frozen_string_literal: true
require "active_support/all"
require "active_model"
module Solid
require_relative "model"
require_relative "value"
require_relative "input"
require_relative "output"
class Process
require "solid/process/version"
require "solid/process/error"
require "solid/process/config"
require "solid/process/caller"
require "solid/process/callbacks"
require "solid/process/class_methods"
require "solid/process/active_record"
require "solid/process/backtrace_cleaner"
require "solid/process/event_logs"
extend ClassMethods
include Callbacks
include ::ActiveSupport::Rescuable
include ::Solid::Output.mixin(config: {addon: {continue: true}})
def self.inherited(subclass)
super
subclass.prepend(Caller)
end
def self.call(arg = nil)
new.call(arg)
end
def self.config
Config.instance
end
def self.configuration(freeze: true, &block)
yield config
config.tap { _1.freeze if freeze }
end
singleton_class.alias_method :configure, :configuration
attr_reader :output, :input, :dependencies
def initialize(arg = nil)
self.dependencies = arg
end
def call(_arg = nil)
raise Error, "#{self.class}#call must be implemented."
end
def with(dependencies)
self.class.new(dependencies.with_indifferent_access.with_defaults(deps&.attributes))
end
def new(dependencies = {})
with(dependencies)
end
def input?
!input.nil?
end
def output?(type = nil)
type.nil? ? !output.nil? : !!output&.is?(type)
end
def dependencies?
!dependencies.nil?
end
def success?(type = nil)
!!output&.success?(type)
end
def failure?(type = nil)
!!output&.failure?(type)
end
def inspect
"#<#{self.class.name} dependencies=#{dependencies.inspect} input=#{input.inspect} output=#{output.inspect}>"
end
def method_missing(name, *args, &block)
name.end_with?("?") ? output&.is?(name.to_s.chomp("?")) : super
end
def respond_to_missing?(name, include_private = false)
name.end_with?("?") || super
end
alias_method :deps, :dependencies
alias_method :deps?, :dependencies?
alias_method :result, :output
alias_method :result?, :output?
private
def dependencies=(arg)
raise Error, "The `#{self.class}#dependencies` is already set." unless dependencies.nil?
@dependencies = self.class.dependencies&.then { arg.instance_of?(_1) ? arg : _1.new(arg) }
end
def input=(arg)
raise Error, "The `#{self.class}#input` is already set." unless input.nil?
@input = self.class.input.then { arg.instance_of?(_1) ? arg : _1.new(arg) }
end
def output_already_set!
raise Error, "The `#{self.class}#output` is already set. " \
"Use `.output` to access the result or create a new instance to call again."
end
def output=(result)
output_already_set! unless output.nil?
raise Error, "The result #{result.inspect} must be a Solid::Output." unless result.is_a?(::Solid::Output)
@output = result
end
def Success!(...)
return self.output = Success(...) if output.nil?
raise Error, "`Success!()` cannot be called because the `#{self.class}#output` is already set."
end
def Failure!(...)
return self.output = Failure(...) if output.nil?
raise Error, "`Failure!()` cannot be called because the `#{self.class}#output` is already set."
end
end
end