solid-process 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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