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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1190b2778ef23e74384d8526ff747c3a741c62a23de0308dc0bcce85c427fef6
4
- data.tar.gz: b3dd1f4009959aed58c08943e3ae642f5322c7d989036161bdaa71559c36fa5d
3
+ metadata.gz: e3b27456b398dffc893e5034953dcb74baa2406beeafd8d88f1be31c26611d90
4
+ data.tar.gz: ac372ee023cc5730e80d00951dda408634efdcc0d25322406d4fe37c85313edf
5
5
  SHA512:
6
- metadata.gz: 3e81a5319038e788e726573abf7f53c2fccdd4ad5cd24d8b57db426cc4d63bd3e2c10bcc041d24c32c268b8ad7abfa61e97fbf3394e096974a2ee6c90262ca3a
7
- data.tar.gz: 3bbdadd724e66a871f3ec83701e9feff39f26fbf59886c83954575e16dc80849ae3d5787acffeec01b43acdafdd4b1d2e19a1b12f55503602a4e71e73317866f
6
+ metadata.gz: '09a4852a76e0e47ef0b3dd02554805647d33b500efb939cc1221f1ff48d538220db9ffa426df2774855d5a014a7de49d28e9e3e7660aca8bab4e12aa85286214'
7
+ data.tar.gz: 2074bc2fef703376047a43e273e138ec038dba78b228a5ec14655351954ecf5b5ad71e50a306480b0dda37d85c6b60920bff0a210581507469709ba52817c0f8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2024-04-14
4
+
5
+ ## [0.2.0] - 2024-03-18
6
+
3
7
  ## [0.1.0] - 2024-03-16
4
8
 
5
9
  - Initial release
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>Ruby on Rails + Business Processes</i></p>
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/serradura/solid-process/maintainability"><img src="https://api.codeclimate.com/v1/badges/643a53e99bb591321c9f/maintainability" /></a>
6
- <a href="https://codeclimate.com/github/serradura/solid-process/test_coverage"><img src="https://api.codeclimate.com/v1/badges/643a53e99bb591321c9f/test_coverage" /></a>
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/serradura/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/serradura/solid-process/blob/master/CODE_OF_CONDUCT.md).
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/serradura/solid-process/blob/master/CODE_OF_CONDUCT.md).
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
- class Solid::Input
4
- require_relative "model"
5
-
6
- def self.inherited(subclass)
7
- subclass.include(::Solid::Model)
8
- end
3
+ require_relative "model"
9
4
 
10
- def self.[](...)
11
- new(...)
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
- module Solid::Model
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(:success, :failure, :output)
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 after_success(*args, &block)
15
- options = args.extract_options!
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 after_failure(*args, &block)
23
- options = args.extract_options!
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 after_output(*args, &block)
31
- options = args.extract_options!
32
- options = options.dup
33
- options[:prepend] = true
22
+ def after_call(*filters, &block)
23
+ set_callback(:call, :after, *filters, &block)
24
+ end
34
25
 
35
- set_callback(:output, :after, *args, options, &block)
26
+ def after_success(*filters, &block)
27
+ set_callback(:success, :after, *filters, &block)
36
28
  end
37
29
 
38
- alias_method :after_result, :after_output
30
+ def after_failure(*filters, &block)
31
+ set_callback(:failure, :after, *filters, &block)
32
+ end
39
33
  end
40
34
  end
41
35
  end
@@ -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
- raise Error, "#{self.class}#call already called. " \
8
- "Use #{self.class}#output to access the result or create a new instance to call again."
9
- end
7
+ output_already_set! if output?
8
+
9
+ self.input = arg
10
10
 
11
- self.input = self.class.input.then { arg.instance_of?(_1) ? arg : _1.new(arg) }
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
- ::BCDD::Result.event_logs(name: self.class.name) do
14
- self.output =
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
- unless klass.is_a?(::Class) && klass < ::Solid::Model
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(::Solid::Input)
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
- unless klass.is_a?(::Class) && klass < ::Solid::Model
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(::Solid::Input)
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Solid
4
4
  class Process
5
- VERSION = "0.1.0"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  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 "bcdd/result"
5
+ require "solid/result"
6
6
 
7
7
  module Solid
8
8
  require "solid/input"
9
- require "solid/result"
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 ::BCDD::Context.mixin(config: {addon: {continue: true}})
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
- attr_accessor :input, :output, :dependencies
43
+ def self.configuration(&block)
44
+ yield config
33
45
 
34
- private :input=, :output=, :dependencies=
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 = self.class.dependencies&.then { arg.instance_of?(_1) ? arg : _1.new(arg) }
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 call(_arg = nil)
53
- raise Error, "#{self.class}#call must be implemented."
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.1.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-03-16 00:00:00.000000000 Z
11
+ date: 2024-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bcdd-result
14
+ name: solid-result
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
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: '1.0'
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: Ruby on Rails + Business Processes
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: Ruby on Rails + Business Processes
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