solid-process 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +5 -5
- data/lib/solid/input.rb +3 -9
- data/lib/solid/model.rb +12 -2
- data/lib/solid/process/callbacks.rb +13 -19
- data/lib/solid/process/caller.rb +19 -15
- data/lib/solid/process/class_methods.rb +4 -12
- data/lib/solid/process/config.rb +35 -0
- data/lib/solid/process/version.rb +1 -1
- data/lib/solid/process.rb +83 -9
- metadata +8 -8
- data/lib/solid/result.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3b27456b398dffc893e5034953dcb74baa2406beeafd8d88f1be31c26611d90
|
4
|
+
data.tar.gz: ac372ee023cc5730e80d00951dda408634efdcc0d25322406d4fe37c85313edf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09a4852a76e0e47ef0b3dd02554805647d33b500efb939cc1221f1ff48d538220db9ffa426df2774855d5a014a7de49d28e9e3e7660aca8bab4e12aa85286214'
|
7
|
+
data.tar.gz: 2074bc2fef703376047a43e273e138ec038dba78b228a5ec14655351954ecf5b5ad71e50a306480b0dda37d85c6b60920bff0a210581507469709ba52817c0f8
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
<p align="center">
|
2
2
|
<h1 align="center" id="-solidprocess">🚄 Solid::Process</h1>
|
3
|
-
<p align="center"><i>
|
3
|
+
<p align="center"><i>Write self-documenting and self-observable business processes in Ruby/Rails.</i></p>
|
4
4
|
<p align="center">
|
5
|
-
<a href="https://codeclimate.com/github/
|
6
|
-
<a href="https://codeclimate.com/github/
|
5
|
+
<a href="https://codeclimate.com/github/solid-process/solid-process/maintainability"><img src="https://api.codeclimate.com/v1/badges/643a53e99bb591321c9f/maintainability" /></a>
|
6
|
+
<a href="https://codeclimate.com/github/solid-process/solid-process/test_coverage"><img src="https://api.codeclimate.com/v1/badges/643a53e99bb591321c9f/test_coverage" /></a>
|
7
7
|
<img src="https://img.shields.io/badge/Ruby%20%3E%3D%202.7%2C%20%3C%3D%20Head-ruby.svg?colorA=444&colorB=333" alt="Ruby">
|
8
8
|
<img src="https://img.shields.io/badge/Rails%20%3E%3D%206.0%2C%20%3C%3D%20Edge-rails.svg?colorA=444&colorB=333" alt="Rails">
|
9
9
|
</p>
|
@@ -54,7 +54,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
54
54
|
|
55
55
|
## Contributing
|
56
56
|
|
57
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
57
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/solid-process/solid-process. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/solid-process/solid-process/blob/main/CODE_OF_CONDUCT.md).
|
58
58
|
|
59
59
|
## License
|
60
60
|
|
@@ -62,4 +62,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
62
62
|
|
63
63
|
## Code of Conduct
|
64
64
|
|
65
|
-
Everyone interacting in the Solid::Process project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
65
|
+
Everyone interacting in the Solid::Process project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/solid-process/solid-process/blob/main/CODE_OF_CONDUCT.md).
|
data/lib/solid/input.rb
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require_relative "model"
|
5
|
-
|
6
|
-
def self.inherited(subclass)
|
7
|
-
subclass.include(::Solid::Model)
|
8
|
-
end
|
3
|
+
require_relative "model"
|
9
4
|
|
10
|
-
|
11
|
-
|
12
|
-
end
|
5
|
+
class Solid::Input
|
6
|
+
include ::Solid::Model
|
13
7
|
end
|
data/lib/solid/model.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require_relative "model/access"
|
3
|
+
require_relative "model/access"
|
5
4
|
|
5
|
+
module Solid::Model
|
6
6
|
extend ::ActiveSupport::Concern
|
7
7
|
|
8
8
|
included do
|
@@ -14,6 +14,16 @@ module Solid::Model
|
|
14
14
|
include ::ActiveModel::Validations::Callbacks
|
15
15
|
end
|
16
16
|
|
17
|
+
module ClassMethods
|
18
|
+
def [](...)
|
19
|
+
new(...)
|
20
|
+
end
|
21
|
+
|
22
|
+
def inherited(subclass)
|
23
|
+
subclass.include(::Solid::Model)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
17
27
|
def inspect
|
18
28
|
"#<#{self.class.name} #{attributes.map { |k, v| "#{k}=#{v.inspect}" }.join(" ")}>"
|
19
29
|
end
|
@@ -5,37 +5,31 @@ class Solid::Process
|
|
5
5
|
def self.included(subclass)
|
6
6
|
subclass.include ActiveSupport::Callbacks
|
7
7
|
|
8
|
-
subclass.define_callbacks(:
|
8
|
+
subclass.define_callbacks(:call, :success, :failure)
|
9
9
|
|
10
10
|
subclass.extend ClassMethods
|
11
11
|
end
|
12
12
|
|
13
13
|
module ClassMethods
|
14
|
-
def
|
15
|
-
|
16
|
-
options = options.dup
|
17
|
-
options[:prepend] = true
|
18
|
-
|
19
|
-
set_callback(:success, :after, *args, options, &block)
|
14
|
+
def before_call(*filters, &block)
|
15
|
+
set_callback(:call, :before, *filters, &block)
|
20
16
|
end
|
21
17
|
|
22
|
-
def
|
23
|
-
|
24
|
-
options = options.dup
|
25
|
-
options[:prepend] = true
|
26
|
-
|
27
|
-
set_callback(:failure, :after, *args, options, &block)
|
18
|
+
def around_call(*filters, &block)
|
19
|
+
set_callback(:call, :around, *filters, &block)
|
28
20
|
end
|
29
21
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
options[:prepend] = true
|
22
|
+
def after_call(*filters, &block)
|
23
|
+
set_callback(:call, :after, *filters, &block)
|
24
|
+
end
|
34
25
|
|
35
|
-
|
26
|
+
def after_success(*filters, &block)
|
27
|
+
set_callback(:success, :after, *filters, &block)
|
36
28
|
end
|
37
29
|
|
38
|
-
|
30
|
+
def after_failure(*filters, &block)
|
31
|
+
set_callback(:failure, :after, *filters, &block)
|
32
|
+
end
|
39
33
|
end
|
40
34
|
end
|
41
35
|
end
|
data/lib/solid/process/caller.rb
CHANGED
@@ -1,31 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rubocop:disable Lint/RescueException
|
3
4
|
class Solid::Process
|
4
5
|
module Caller
|
5
6
|
def call(arg = nil)
|
6
|
-
if output?
|
7
|
-
|
8
|
-
|
9
|
-
end
|
7
|
+
output_already_set! if output?
|
8
|
+
|
9
|
+
self.input = arg
|
10
10
|
|
11
|
-
|
11
|
+
run_callbacks(:call) do
|
12
|
+
::Solid::Result.event_logs(name: self.class.name) do
|
13
|
+
self.output =
|
14
|
+
if dependencies&.invalid?
|
15
|
+
Failure(:invalid_dependencies, dependencies: dependencies)
|
16
|
+
elsif input.invalid?
|
17
|
+
Failure(:invalid_input, input: input)
|
18
|
+
else
|
19
|
+
super(input.attributes.deep_symbolize_keys)
|
20
|
+
end
|
21
|
+
rescue ::Exception => exception
|
22
|
+
rescue_with_handler(exception) || raise
|
12
23
|
|
13
|
-
|
14
|
-
|
15
|
-
if dependencies&.invalid?
|
16
|
-
Failure(:invalid_dependencies, dependencies: dependencies)
|
17
|
-
elsif input.invalid?
|
18
|
-
Failure(:invalid_input, input: input)
|
19
|
-
else
|
20
|
-
super(input.attributes.deep_symbolize_keys)
|
21
|
-
end
|
24
|
+
output
|
25
|
+
end
|
22
26
|
end
|
23
27
|
|
24
28
|
run_callbacks(:success) if output.success?
|
25
29
|
run_callbacks(:failure) if output.failure?
|
26
|
-
run_callbacks(:output)
|
27
30
|
|
28
31
|
output
|
29
32
|
end
|
30
33
|
end
|
31
34
|
end
|
35
|
+
# rubocop:enable Lint/RescueException
|
@@ -5,11 +5,7 @@ class Solid::Process
|
|
5
5
|
def input=(klass)
|
6
6
|
const_defined?(:Input, false) and raise Error, "#{const_get(:Input, false)} class already defined"
|
7
7
|
|
8
|
-
|
9
|
-
raise ArgumentError, "#{klass.inspect} must be a class that includes #{::Solid::Model}"
|
10
|
-
end
|
11
|
-
|
12
|
-
const_set(:Input, klass)
|
8
|
+
const_set(:Input, Config::SolidModel[klass])
|
13
9
|
end
|
14
10
|
|
15
11
|
def input(&block)
|
@@ -17,7 +13,7 @@ class Solid::Process
|
|
17
13
|
|
18
14
|
block.nil? and raise Error, "#{self}::Input is undefined. Use #{self}.input { ... } to define it."
|
19
15
|
|
20
|
-
klass = ::Class.new(
|
16
|
+
klass = ::Class.new(Config.instance.input_class)
|
21
17
|
klass.class_eval(&block)
|
22
18
|
|
23
19
|
self.input = klass
|
@@ -26,11 +22,7 @@ class Solid::Process
|
|
26
22
|
def dependencies=(klass)
|
27
23
|
const_defined?(:Dependencies, false) and raise Error, "#{const_get(:Dependencies, false)} class already defined"
|
28
24
|
|
29
|
-
|
30
|
-
raise ArgumentError, "#{klass.inspect} must be a class that includes #{::Solid::Model}"
|
31
|
-
end
|
32
|
-
|
33
|
-
const_set(:Dependencies, klass)
|
25
|
+
const_set(:Dependencies, Config::SolidModel[klass])
|
34
26
|
end
|
35
27
|
|
36
28
|
def dependencies(&block)
|
@@ -38,7 +30,7 @@ class Solid::Process
|
|
38
30
|
|
39
31
|
return if block.nil?
|
40
32
|
|
41
|
-
klass = ::Class.new(
|
33
|
+
klass = ::Class.new(Config.instance.dependencies_class)
|
42
34
|
klass.class_eval(&block)
|
43
35
|
|
44
36
|
self.dependencies = klass
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Solid::Process
|
4
|
+
class Config
|
5
|
+
SolidModel = ->(klass) do
|
6
|
+
return klass if klass.is_a?(::Class) && klass < ::Solid::Model
|
7
|
+
|
8
|
+
raise ArgumentError, "#{klass.inspect} must be a class that includes #{::Solid::Model}"
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :input_class, :dependencies_class
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
self.input_class = ::Solid::Input
|
15
|
+
self.dependencies_class = ::Solid::Input
|
16
|
+
end
|
17
|
+
|
18
|
+
def input_class=(klass)
|
19
|
+
@input_class = SolidModel[klass]
|
20
|
+
end
|
21
|
+
|
22
|
+
def dependencies_class=(klass)
|
23
|
+
@dependencies_class = SolidModel[klass]
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method :deps_class, :dependencies_class
|
27
|
+
alias_method :deps_class=, :dependencies_class=
|
28
|
+
|
29
|
+
class << self
|
30
|
+
attr_reader :instance
|
31
|
+
end
|
32
|
+
|
33
|
+
@instance = new
|
34
|
+
end
|
35
|
+
end
|
data/lib/solid/process.rb
CHANGED
@@ -2,15 +2,23 @@
|
|
2
2
|
|
3
3
|
require "active_support/all"
|
4
4
|
require "active_model"
|
5
|
-
require "
|
5
|
+
require "solid/result"
|
6
6
|
|
7
7
|
module Solid
|
8
8
|
require "solid/input"
|
9
|
-
|
9
|
+
|
10
|
+
def self.Success(...)
|
11
|
+
::Solid::Output::Success(...)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.Failure(...)
|
15
|
+
::Solid::Output::Failure(...)
|
16
|
+
end
|
10
17
|
|
11
18
|
class Process
|
12
19
|
require "solid/process/version"
|
13
20
|
require "solid/process/error"
|
21
|
+
require "solid/process/config"
|
14
22
|
require "solid/process/caller"
|
15
23
|
require "solid/process/callbacks"
|
16
24
|
require "solid/process/class_methods"
|
@@ -18,23 +26,46 @@ module Solid
|
|
18
26
|
|
19
27
|
extend ClassMethods
|
20
28
|
|
21
|
-
include
|
29
|
+
include Callbacks
|
30
|
+
include ::ActiveSupport::Rescuable
|
31
|
+
include ::Solid::Output.mixin(config: {addon: {continue: true}})
|
22
32
|
|
23
33
|
def self.inherited(subclass)
|
34
|
+
super
|
35
|
+
|
24
36
|
subclass.prepend(Caller)
|
25
|
-
subclass.include(Callbacks)
|
26
37
|
end
|
27
38
|
|
28
39
|
def self.call(arg = nil)
|
29
40
|
new.call(arg)
|
30
41
|
end
|
31
42
|
|
32
|
-
|
43
|
+
def self.configuration(&block)
|
44
|
+
yield config
|
33
45
|
|
34
|
-
|
46
|
+
config.freeze
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.config
|
50
|
+
Config.instance
|
51
|
+
end
|
52
|
+
|
53
|
+
attr_reader :output, :input, :dependencies
|
35
54
|
|
36
55
|
def initialize(arg = nil)
|
37
|
-
self.dependencies =
|
56
|
+
self.dependencies = arg
|
57
|
+
end
|
58
|
+
|
59
|
+
def call(_arg = nil)
|
60
|
+
raise Error, "#{self.class}#call must be implemented."
|
61
|
+
end
|
62
|
+
|
63
|
+
def with(dependencies)
|
64
|
+
self.class.new(dependencies.with_indifferent_access.with_defaults(deps&.attributes))
|
65
|
+
end
|
66
|
+
|
67
|
+
def new(dependencies = {})
|
68
|
+
with(dependencies)
|
38
69
|
end
|
39
70
|
|
40
71
|
def input?
|
@@ -49,8 +80,12 @@ module Solid
|
|
49
80
|
!dependencies.nil?
|
50
81
|
end
|
51
82
|
|
52
|
-
def
|
53
|
-
|
83
|
+
def success?(type = nil)
|
84
|
+
!!output&.success?(type)
|
85
|
+
end
|
86
|
+
|
87
|
+
def failure?(type = nil)
|
88
|
+
!!output&.failure?(type)
|
54
89
|
end
|
55
90
|
|
56
91
|
def inspect
|
@@ -69,5 +104,44 @@ module Solid
|
|
69
104
|
alias_method :deps?, :dependencies?
|
70
105
|
alias_method :result, :output
|
71
106
|
alias_method :result?, :output?
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def dependencies=(arg)
|
111
|
+
raise Error, "The `#{self.class}#dependencies` is already set." unless dependencies.nil?
|
112
|
+
|
113
|
+
@dependencies = self.class.dependencies&.then { arg.instance_of?(_1) ? arg : _1.new(arg) }
|
114
|
+
end
|
115
|
+
|
116
|
+
def input=(arg)
|
117
|
+
raise Error, "The `#{self.class}#input` is already set." unless input.nil?
|
118
|
+
|
119
|
+
@input = self.class.input.then { arg.instance_of?(_1) ? arg : _1.new(arg) }
|
120
|
+
end
|
121
|
+
|
122
|
+
def output_already_set!
|
123
|
+
raise Error, "The `#{self.class}#output` is already set. " \
|
124
|
+
"Use `.output` to access the result or create a new instance to call again."
|
125
|
+
end
|
126
|
+
|
127
|
+
def output=(result)
|
128
|
+
output_already_set! unless output.nil?
|
129
|
+
|
130
|
+
raise Error, "The result #{result.inspect} must be a Solid::Output." unless result.is_a?(::Solid::Output)
|
131
|
+
|
132
|
+
@output = result
|
133
|
+
end
|
134
|
+
|
135
|
+
def Success!(...)
|
136
|
+
return self.output = Success(...) if output.nil?
|
137
|
+
|
138
|
+
raise Error, "`Success!()` cannot be called because the `#{self.class}#output` is already set."
|
139
|
+
end
|
140
|
+
|
141
|
+
def Failure!(...)
|
142
|
+
return self.output = Failure(...) if output.nil?
|
143
|
+
|
144
|
+
raise Error, "`Failure!()` cannot be called because the `#{self.class}#output` is already set."
|
145
|
+
end
|
72
146
|
end
|
73
147
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solid-process
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo Serradura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: solid-result
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activemodel
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '2.5'
|
61
|
-
description:
|
61
|
+
description: Write self-documenting and self-observable business processes in Ruby/Rails.
|
62
62
|
email:
|
63
63
|
- rodrigo.serradura@gmail.com
|
64
64
|
executables: []
|
@@ -92,9 +92,9 @@ files:
|
|
92
92
|
- lib/solid/process/callbacks.rb
|
93
93
|
- lib/solid/process/caller.rb
|
94
94
|
- lib/solid/process/class_methods.rb
|
95
|
+
- lib/solid/process/config.rb
|
95
96
|
- lib/solid/process/error.rb
|
96
97
|
- lib/solid/process/version.rb
|
97
|
-
- lib/solid/result.rb
|
98
98
|
- lib/solid/validators/all.rb
|
99
99
|
- lib/solid/validators/bool_validator.rb
|
100
100
|
- lib/solid/validators/email_validator.rb
|
@@ -131,5 +131,5 @@ requirements: []
|
|
131
131
|
rubygems_version: 3.1.6
|
132
132
|
signing_key:
|
133
133
|
specification_version: 4
|
134
|
-
summary:
|
134
|
+
summary: Write self-documenting and self-observable business processes in Ruby/Rails.
|
135
135
|
test_files: []
|
data/lib/solid/result.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Solid
|
4
|
-
Output = ::BCDD::Context
|
5
|
-
|
6
|
-
Result = ::BCDD::Context
|
7
|
-
Success = Result::Success
|
8
|
-
Failure = Result::Failure
|
9
|
-
|
10
|
-
def self.Success(...)
|
11
|
-
Result::Success(...)
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.Failure(...)
|
15
|
-
Result::Failure(...)
|
16
|
-
end
|
17
|
-
end
|