solid-process 0.3.0 → 0.4.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: e3b27456b398dffc893e5034953dcb74baa2406beeafd8d88f1be31c26611d90
4
- data.tar.gz: ac372ee023cc5730e80d00951dda408634efdcc0d25322406d4fe37c85313edf
3
+ metadata.gz: 973ae538a96362750bac5c31245c2e8390144c4d67688940fa8b28f2ee27e538
4
+ data.tar.gz: 057c4bbbd8e2c4fc955c548a714fdb7fbe4396e1b8d624dc7702cc4750e929fa
5
5
  SHA512:
6
- metadata.gz: '09a4852a76e0e47ef0b3dd02554805647d33b500efb939cc1221f1ff48d538220db9ffa426df2774855d5a014a7de49d28e9e3e7660aca8bab4e12aa85286214'
7
- data.tar.gz: 2074bc2fef703376047a43e273e138ec038dba78b228a5ec14655351954ecf5b5ad71e50a306480b0dda37d85c6b60920bff0a210581507469709ba52817c0f8
6
+ metadata.gz: 20c3a43c503dfc26560ca25cb20a3d4d53f2014de3f9883bfbd872e7759881fc636da985f335d53f9c9c81b730b797f9759649543b49644ddf2e774222a4d2cc
7
+ data.tar.gz: 3802c1bab8d942f351099e0510f9cfae3d86b110508cea3d96b61c4bd4eb5953c249b2280d4565bc3b02990744d908f229267edffc88eab38100664bebe83959
data/CHANGELOG.md CHANGED
@@ -1,9 +1,88 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.4.0] - 2024-06-23
4
+
5
+ ### Added
6
+
7
+ - Add `Solid::Process.configuration(freeze: true)`.
8
+
9
+ - Add `Solid::Process::EventLogs::BasicLoggerListener`.
10
+
11
+ - Add `Solid::Process::BacktraceCleaner`.
12
+
13
+ - Add `Solid::Process.configure` as an alias to `Solid::Process.configuration`.
14
+
15
+ - Add `Solid::Value` to allow defining a value object.
16
+
17
+ - `Solid::Model`
18
+ - Add `after_initialize` callback.
19
+ - Add `#[]` to access instance attributes.
20
+
21
+ - `solid/validators`
22
+ - Add `id_validator`, to check if the value is a positive integer or a string that represents a positive integer.
23
+ - Add `is_validator`, to check if the value satisfy the given predicate methods.
24
+
25
+ ### Changed
26
+
27
+ - Replace the usage of `deep_symbolize_keys` with `symbolize_keys` to perform the call more efficiently.
28
+
29
+ - Change `email_validator` and `uuid_validator` to use `I18n` messages.
30
+
31
+ - Relax `ActiveModel` dependency to `>= 6.0`.
32
+
33
+ ### Removed
34
+
35
+ - Remove some validators:
36
+ - `bool_validator`
37
+ - `is_a_validator`
38
+ - `persisted_validator`
39
+
3
40
  ## [0.3.0] - 2024-04-14
4
41
 
42
+ ### Changed
43
+
44
+ - Replace `bcdd-result` gem `solid-result` gem. This change removes the constant aliases `Solid::Output` and `Solid::Result`, as they are no longer needed.
45
+
5
46
  ## [0.2.0] - 2024-03-18
6
47
 
48
+ ### Added
49
+
50
+ - Add `Solid::Process#success?`, `Solid::Process#failure?` that delegate to `Solid::Process#output.success?` and `Solid::Process#output.failure?`.
51
+
52
+ - Add `Solid::Process#with` method to create a new process instance with new dependencies.
53
+
54
+ - Add `Solid::Process#new` method. It's similar to `Solid::Process#with` but does not require passing the dependencies. If nothing is passed, it will use the same dependencies.
55
+
56
+ - Add `rescue_from` (from `::ActiveSupport::Rescuable`) method to `Solid::Process` to rescue exceptions and return a `Solid::Output`.
57
+
58
+ - Add `Solid::Process.config` and `Solid::Process.configuration` methods to define a configuration for all processes.
59
+
60
+ ### Changed
61
+
62
+ - Move `Solid::Input` features to `Solid::Model` module. This change does not promote breaking changes.
63
+
7
64
  ## [0.1.0] - 2024-03-16
8
65
 
9
- - Initial release
66
+ ### Added
67
+
68
+ - Add `Solid::Model` module to define a model with attributes and validations.
69
+ - It includes `ActiveModel::Api`, `ActiveModel::Access`, `ActiveModel::Attributes`, `ActiveModel::Dirty`, `ActiveModel::Validations::Callbacks`.
70
+
71
+ - Add `Solid::Input` class (which includes `Solid::Model`) to define an input object with attributes and validations.
72
+
73
+ - Add `Solid::Output` and `Solid::Result` as constant aliases of `BCDD::Context`.
74
+
75
+ - Add `Solid::Success()` and `Solid::Failure()` methods to create `BCDD::Context` instances.
76
+
77
+ - Add `Solid::Process` class to be inherited and define a process with inputs, outputs, and steps.
78
+
79
+ - Add several ActiveModel validations to be used in `Solid::Model` and `Solid::Input` classes.
80
+ - `bool_validator`
81
+ - `email_validator`
82
+ - `instance_of_validator`
83
+ - `is_a_validator`
84
+ - `kind_of_validator`
85
+ - `persisted_validator`
86
+ - `respond_to_validator`
87
+ - `singleton_validator`
88
+ - `uuid_validator`
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <p align="center">
2
- <h1 align="center" id="-solidprocess">🚄 Solid::Process</h1>
3
- <p align="center"><i>Write self-documenting and self-observable business processes in Ruby/Rails.</i></p>
2
+ <h1 align="center" id="-solidprocess">⚛️ Solid::Process</h1>
3
+ <p align="center"><i>Write business logic for Ruby/Rails that scales.</i></p>
4
4
  <p align="center">
5
5
  <a href="https://codeclimate.com/github/solid-process/solid-process/maintainability"><img src="https://api.codeclimate.com/v1/badges/643a53e99bb591321c9f/maintainability" /></a>
6
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>
@@ -22,6 +22,26 @@ This library is tested against:
22
22
  | 3.3 | ✅ | ✅ | ✅ | ✅ | ✅ |
23
23
  | Head | | | | ✅ | ✅ |
24
24
 
25
+ ## Introduction
26
+
27
+ `solid-process` is a Ruby/Rails library designed to encapsulate business logic into manageable processes. It simplifies writing, testing, maintaining, and evolving your code, ensuring it remains clear and approachable as your application scales.
28
+
29
+ **Key Objectives:**
30
+
31
+ 1. **Seamless Rails integration:** Designed to fully complement the Ruby on Rails framework, this library integrates smoothly without conflicting with existing Rails conventions and capabilities.
32
+
33
+ 2. **Support progressive mastery:** Offers an intuitive entry point for novices while providing robust, advanced features that cater to experienced developers.
34
+
35
+ 3. **Promote conceptual integrity and rapid onboarding:** By maintaining a consistent design philosophy, `solid-process` reduces the learning curve for new developers, allowing them to contribute more effectively and quickly.
36
+
37
+ 4. **Minimize technical debt:** Facilitate smoother transitions and updates as your application expands and your team size increases.
38
+
39
+ 5. **Enhanced observability:** Equipped with sophisticated instrumentation mechanisms, the library enables detailed logging and tracing without compromising clarity, even when processes are nested. This ensures the code is both easy to understand and to observe.
40
+
41
+ ### Examples
42
+
43
+ Checkout the [solid-rails-app](https://github.com/solid-process/solid-rails-app) for a full example of how to use `solid-process` in a Rails application. Or take a look at the [examples](examples) folder in this repository.
44
+
25
45
  ## Installation
26
46
 
27
47
  Add this line to your application's Gemfile:
data/lib/solid/input.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "model"
4
-
5
3
  class Solid::Input
6
4
  include ::Solid::Model
7
5
  end
data/lib/solid/model.rb CHANGED
@@ -5,6 +5,16 @@ require_relative "model/access"
5
5
  module Solid::Model
6
6
  extend ::ActiveSupport::Concern
7
7
 
8
+ module ClassMethods
9
+ def [](...)
10
+ new(...)
11
+ end
12
+
13
+ def inherited(subclass)
14
+ subclass.include(::Solid::Model)
15
+ end
16
+ end
17
+
8
18
  included do
9
19
  include ::ActiveModel.const_defined?(:Api, false) ? ::ActiveModel::Api : ::ActiveModel::Model
10
20
  include ::ActiveModel.const_defined?(:Access, false) ? ::ActiveModel::Access : ::Solid::Model::Access
@@ -12,19 +22,21 @@ module Solid::Model
12
22
  include ::ActiveModel::Attributes
13
23
  include ::ActiveModel::Dirty
14
24
  include ::ActiveModel::Validations::Callbacks
25
+
26
+ extend ActiveModel::Callbacks
27
+
28
+ define_model_callbacks :initialize, only: :after
15
29
  end
16
30
 
17
- module ClassMethods
18
- def [](...)
19
- new(...)
20
- end
31
+ def initialize(...)
32
+ super
21
33
 
22
- def inherited(subclass)
23
- subclass.include(::Solid::Model)
24
- end
34
+ run_callbacks(:initialize)
25
35
  end
26
36
 
27
37
  def inspect
28
38
  "#<#{self.class.name} #{attributes.map { |k, v| "#{k}=#{v.inspect}" }.join(" ")}>"
29
39
  end
40
+
41
+ alias_method :[], :public_send
30
42
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "solid/result"
4
+
5
+ module Solid
6
+ def self.Success(...)
7
+ ::Solid::Output::Success(...)
8
+ end
9
+
10
+ def self.Failure(...)
11
+ ::Solid::Output::Failure(...)
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solid::Process::BacktraceCleaner < ActiveSupport::BacktraceCleaner
4
+ def initialize
5
+ super
6
+
7
+ add_blocks_silencer
8
+ end
9
+
10
+ private
11
+
12
+ BLOCKS_PATTERN = /in [`']block in|in `then'|internal:kernel|block \(\d+ levels?\) in/.freeze
13
+
14
+ def add_blocks_silencer
15
+ add_silencer { |line| line.match?(BLOCKS_PATTERN) }
16
+ end
17
+ end
@@ -16,7 +16,7 @@ class Solid::Process
16
16
  elsif input.invalid?
17
17
  Failure(:invalid_input, input: input)
18
18
  else
19
- super(input.attributes.deep_symbolize_keys)
19
+ super(input.attributes.symbolize_keys)
20
20
  end
21
21
  rescue ::Exception => exception
22
22
  rescue_with_handler(exception) || raise
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solid::Process::EventLogs::BasicLoggerListener
4
+ include ActiveSupport::Configurable
5
+ include Solid::Result::EventLogs::Listener
6
+
7
+ config_accessor(:logger, :backtrace_cleaner)
8
+
9
+ self.logger = ActiveSupport::Logger.new($stdout)
10
+ self.backtrace_cleaner = Solid::Process::BacktraceCleaner.new
11
+
12
+ module MessagesNesting
13
+ MAP_STEP_METHOD = lambda do |record_result|
14
+ kind, type, value = record_result.values_at(:kind, :type, :value)
15
+
16
+ value_keys = "#{value.keys.join(":, ")}:"
17
+ value_keys = "" if value_keys == ":"
18
+
19
+ case type
20
+ when :_given_ then "Given(#{value_keys})"
21
+ when :_continue_ then "Continue(#{value_keys})"
22
+ else "#{kind.capitalize}(:#{type}, #{value_keys})"
23
+ end
24
+ end
25
+
26
+ MAP_STEP_MESSAGE = lambda do |record|
27
+ step = MAP_STEP_METHOD[record[:result]]
28
+
29
+ method_name = record.dig(:and_then, :method_name)
30
+
31
+ " * #{step} from method: #{method_name}".chomp("from method: ").chomp(" ")
32
+ end
33
+
34
+ MAP_IDS_WITH_MESSAGES = lambda do |records|
35
+ process_ids = []
36
+
37
+ records.each_with_object([]) do |record, messages|
38
+ current = record[:current]
39
+
40
+ current_id = current[:id]
41
+
42
+ unless process_ids.include?(current_id)
43
+ process_ids << current_id
44
+
45
+ id, name, desc = current.values_at(:id, :name, :desc)
46
+
47
+ messages << [current_id, "##{id} #{name} - #{desc}".chomp("- ").chomp(" ")]
48
+ end
49
+
50
+ messages << [current_id, MAP_STEP_MESSAGE[record]]
51
+ end
52
+ end
53
+
54
+ def self.map(event_logs)
55
+ ids_level_parent = event_logs.dig(:metadata, :ids, :level_parent)
56
+
57
+ messages = MAP_IDS_WITH_MESSAGES[event_logs[:records]]
58
+
59
+ messages.map { |(id, msg)| "#{" " * ids_level_parent[id].first}#{msg}" }
60
+ end
61
+ end
62
+
63
+ def on_finish(event_logs:)
64
+ messages = MessagesNesting.map(event_logs)
65
+
66
+ logger.info messages.join("\n")
67
+ end
68
+
69
+ def before_interruption(exception:, event_logs:)
70
+ messages = MessagesNesting.map(event_logs)
71
+
72
+ logger.info messages.join("\n")
73
+
74
+ cleaned_backtrace = backtrace_cleaner.clean(exception.backtrace).join("\n ")
75
+
76
+ logger.error "\nException:\n #{exception.message} (#{exception.class})\n\nBacktrace:\n #{cleaned_backtrace}"
77
+ end
78
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solid::Process
4
+ module EventLogs
5
+ require_relative "event_logs/basic_logger_listener"
6
+ end
7
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Solid
4
4
  class Process
5
- VERSION = "0.3.0"
5
+ VERSION = "0.4.0"
6
6
  end
7
7
  end
data/lib/solid/process.rb CHANGED
@@ -2,18 +2,12 @@
2
2
 
3
3
  require "active_support/all"
4
4
  require "active_model"
5
- require "solid/result"
6
5
 
7
6
  module Solid
8
- require "solid/input"
9
-
10
- def self.Success(...)
11
- ::Solid::Output::Success(...)
12
- end
13
-
14
- def self.Failure(...)
15
- ::Solid::Output::Failure(...)
16
- end
7
+ require_relative "model"
8
+ require_relative "value"
9
+ require_relative "input"
10
+ require_relative "output"
17
11
 
18
12
  class Process
19
13
  require "solid/process/version"
@@ -23,6 +17,8 @@ module Solid
23
17
  require "solid/process/callbacks"
24
18
  require "solid/process/class_methods"
25
19
  require "solid/process/active_record"
20
+ require "solid/process/backtrace_cleaner"
21
+ require "solid/process/event_logs"
26
22
 
27
23
  extend ClassMethods
28
24
 
@@ -40,15 +36,17 @@ module Solid
40
36
  new.call(arg)
41
37
  end
42
38
 
43
- def self.configuration(&block)
39
+ def self.config
40
+ Config.instance
41
+ end
42
+
43
+ def self.configuration(freeze: true, &block)
44
44
  yield config
45
45
 
46
- config.freeze
46
+ config.tap { _1.freeze if freeze }
47
47
  end
48
48
 
49
- def self.config
50
- Config.instance
51
- end
49
+ singleton_class.alias_method :configure, :configuration
52
50
 
53
51
  attr_reader :output, :input, :dependencies
54
52
 
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class EmailValidator < ActiveModel::EachValidator
4
- def validate_each(obj, attribute, value)
4
+ def validate_each(model, attribute, value)
5
+ return model.errors.add(attribute, :blank, **options) if value.blank?
6
+
5
7
  return if value.is_a?(String) && URI::MailTo::EMAIL_REGEXP.match?(value)
6
8
 
7
- obj.errors.add attribute, (options[:message] || "is not an email")
9
+ model.errors.add(attribute, :invalid, **options)
8
10
  end
9
11
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "solid/validators"
4
+
5
+ class IdValidator < ActiveModel::EachValidator
6
+ OPTIONS = {only_integer: true, greater_than: 0}.freeze
7
+
8
+ def validate_each(model, attribute, value)
9
+ opts = OPTIONS.merge(options.except(*OPTIONS.keys))
10
+
11
+ opts[:attributes] = attribute
12
+
13
+ ::ActiveModel::Validations::NumericalityValidator.new(opts).validate_each(model, attribute, value)
14
+ end
15
+
16
+ private_constant :OPTIONS
17
+ end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "solid/validators"
4
+
3
5
  class InstanceOfValidator < ActiveModel::EachValidator
4
- def validate_each(obj, attribute, value)
6
+ def validate_each(model, attribute, value)
5
7
  with_option = Array.wrap(options[:with] || options[:in])
6
8
 
7
9
  return if with_option.any? { |type| value.instance_of?(type) }
8
10
 
9
- expectation = with_option.map(&:name).join(" | ")
11
+ message = "is not an instance of #{with_option.map(&:name).join(" | ")}"
10
12
 
11
- obj.errors.add(attribute, (options[:message] || "is not an instance of #{expectation}"))
13
+ Solid::Validators.add_error(model, attribute, message, options)
12
14
  end
13
15
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "solid/validators"
4
+
5
+ class IsValidator < ActiveModel::EachValidator
6
+ def validate_each(model, attribute, value)
7
+ with_option = Array.wrap(options[:with] || options[:in])
8
+
9
+ return if with_option.all? do |predicate|
10
+ raise ArgumentError, "expected a predicate method, got #{predicate.inspect}" unless predicate.end_with?("?")
11
+
12
+ value.try(predicate)
13
+ end
14
+
15
+ message = "does not satisfy the predicate#{"s" if with_option.size > 1}: #{with_option.join(" & ")}"
16
+
17
+ Solid::Validators.add_error(model, attribute, message, options)
18
+ end
19
+ end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "solid/validators"
4
+
3
5
  class KindOfValidator < ActiveModel::EachValidator
4
- def validate_each(obj, attribute, value)
6
+ def validate_each(model, attribute, value)
5
7
  with_option = Array.wrap(options[:with] || options[:in])
6
8
 
7
9
  return if with_option.any? { |type| value.is_a?(type) }
8
10
 
9
- expectation = with_option.map(&:name).join(" | ")
11
+ message = "is not a #{with_option.map(&:name).join(" | ")}"
10
12
 
11
- obj.errors.add(attribute, (options[:message] || "is not a #{expectation}"))
13
+ Solid::Validators.add_error(model, attribute, message, options)
12
14
  end
13
15
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "solid/validators"
4
+
3
5
  class RespondToValidator < ActiveModel::EachValidator
4
- def validate_each(obj, attribute, value)
6
+ def validate_each(model, attribute, value)
5
7
  with_option = Array.wrap(options[:with] || options[:in])
6
8
 
7
9
  return if with_option.all? { value.respond_to?(_1) }
8
10
 
9
- expectation = with_option.map(&:inspect).join(" & ")
11
+ message = "does not respond to #{with_option.map(&:inspect).join(" & ")}"
10
12
 
11
- obj.errors.add(attribute, (options[:message] || "does not respond to #{expectation}"))
13
+ Solid::Validators.add_error(model, attribute, message, options)
12
14
  end
13
15
  end
@@ -1,21 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "solid/validators"
4
+
3
5
  class SingletonValidator < ActiveModel::EachValidator
4
- def validate_each(obj, attribute, value)
6
+ def validate_each(model, attribute, value)
5
7
  with_option = Array.wrap(options[:with] || options[:in])
6
8
 
7
- unless value.is_a?(Module)
8
- return obj.errors.add(attribute, options[:message] || "is not a class or module")
9
- end
9
+ return model.errors.add(attribute, options[:message] || "is not a class or module") unless value.is_a?(Module)
10
10
 
11
- is_valid = with_option.any? do |type|
12
- type.is_a?(Module) or raise ArgumentError, "#{type.inspect} is not a class or module"
11
+ return if with_option.any? do |type|
12
+ raise ArgumentError, "#{type.inspect} is not a class or module" unless type.is_a?(Module)
13
13
 
14
14
  value == type || (value < type || value.is_a?(type))
15
15
  end
16
16
 
17
- expectation = with_option.map(&:name).join(" | ")
17
+ message = "is not #{with_option.map(&:name).join(" | ")}"
18
18
 
19
- is_valid or obj.errors.add(attribute, (options[:message] || "is not #{expectation}"))
19
+ Solid::Validators.add_error(model, attribute, message, options)
20
20
  end
21
21
  end
@@ -5,16 +5,16 @@ class UuidValidator < ActiveModel::EachValidator
5
5
  CASE_SENSITIVE = /\A#{PATTERN}\z/.freeze
6
6
  CASE_INSENSITIVE = /\A#{PATTERN}\z/i.freeze
7
7
 
8
- def validate_each(obj, attribute, value)
8
+ def validate_each(model, attribute, value)
9
9
  case_sensitive = options.fetch(:case_sensitive, true)
10
10
 
11
+ return model.errors.add(attribute, :blank, **options) if value.blank?
12
+
11
13
  regexp = case_sensitive ? CASE_SENSITIVE : CASE_INSENSITIVE
12
14
 
13
15
  return if value.is_a?(String) && value.match?(regexp)
14
16
 
15
- message = options[:message] || "is not a valid UUID (case #{case_sensitive ? "sensitive" : "insensitive"})"
16
-
17
- obj.errors.add(attribute, message)
17
+ model.errors.add(attribute, :invalid, **options)
18
18
  end
19
19
 
20
20
  private_constant :PATTERN
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solid
4
+ module Validators
5
+ def self.add_error(model, attribute, message, options)
6
+ if ActiveModel.const_defined?(:Error)
7
+ model.errors.add(attribute, **options.merge(message: message))
8
+ else
9
+ model.errors.add(attribute, options.fetch(:message, message))
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solid::Value
4
+ module ClassMethods
5
+ UNDEFINED = ::Object.new
6
+
7
+ def new(value = UNDEFINED)
8
+ return value if value.is_a?(self)
9
+
10
+ UNDEFINED.equal?(value) ? super() : super(value: value)
11
+ end
12
+
13
+ def attribute(...)
14
+ super(:value, ...)
15
+ end
16
+
17
+ def validates(...)
18
+ super(:value, ...)
19
+ end
20
+ end
21
+
22
+ def self.included(subclass)
23
+ subclass.include Solid::Model
24
+ subclass.extend ClassMethods
25
+ subclass.attribute
26
+ end
27
+
28
+ def ==(other)
29
+ other.is_a?(self.class) && other.value == value
30
+ end
31
+
32
+ def hash
33
+ value.hash
34
+ end
35
+
36
+ def to_s
37
+ value.to_s
38
+ end
39
+
40
+ alias_method :eql?, :==
41
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid-process
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.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-04-14 00:00:00.000000000 Z
11
+ date: 2024-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: solid-result
@@ -31,9 +31,6 @@ dependencies:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '6.0'
34
- - - "<"
35
- - !ruby/object:Gem::Version
36
- version: '8.0'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
@@ -41,9 +38,6 @@ dependencies:
41
38
  - - ">="
42
39
  - !ruby/object:Gem::Version
43
40
  version: '6.0'
44
- - - "<"
45
- - !ruby/object:Gem::Version
46
- version: '8.0'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: appraisal
49
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,7 +52,7 @@ dependencies:
58
52
  - - "~>"
59
53
  - !ruby/object:Gem::Version
60
54
  version: '2.5'
61
- description: Write self-documenting and self-observable business processes in Ruby/Rails.
55
+ description: Write business logic for Ruby/Rails that scales.
62
56
  email:
63
57
  - rodrigo.serradura@gmail.com
64
58
  executables: []
@@ -87,24 +81,28 @@ files:
87
81
  - lib/solid/input.rb
88
82
  - lib/solid/model.rb
89
83
  - lib/solid/model/access.rb
84
+ - lib/solid/output.rb
90
85
  - lib/solid/process.rb
91
86
  - lib/solid/process/active_record.rb
87
+ - lib/solid/process/backtrace_cleaner.rb
92
88
  - lib/solid/process/callbacks.rb
93
89
  - lib/solid/process/caller.rb
94
90
  - lib/solid/process/class_methods.rb
95
91
  - lib/solid/process/config.rb
96
92
  - lib/solid/process/error.rb
93
+ - lib/solid/process/event_logs.rb
94
+ - lib/solid/process/event_logs/basic_logger_listener.rb
97
95
  - lib/solid/process/version.rb
98
- - lib/solid/validators/all.rb
99
- - lib/solid/validators/bool_validator.rb
96
+ - lib/solid/validators.rb
100
97
  - lib/solid/validators/email_validator.rb
98
+ - lib/solid/validators/id_validator.rb
101
99
  - lib/solid/validators/instance_of_validator.rb
102
- - lib/solid/validators/is_a_validator.rb
100
+ - lib/solid/validators/is_validator.rb
103
101
  - lib/solid/validators/kind_of_validator.rb
104
- - lib/solid/validators/persisted_validator.rb
105
102
  - lib/solid/validators/respond_to_validator.rb
106
103
  - lib/solid/validators/singleton_validator.rb
107
104
  - lib/solid/validators/uuid_validator.rb
105
+ - lib/solid/value.rb
108
106
  homepage: https://github.com/serradura/solid-process
109
107
  licenses:
110
108
  - MIT
@@ -128,8 +126,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
126
  - !ruby/object:Gem::Version
129
127
  version: '0'
130
128
  requirements: []
131
- rubygems_version: 3.1.6
129
+ rubygems_version: 3.5.10
132
130
  signing_key:
133
131
  specification_version: 4
134
- summary: Write self-documenting and self-observable business processes in Ruby/Rails.
132
+ summary: Write business logic for Ruby/Rails that scales.
135
133
  test_files: []
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "instance_of_validator"
4
- require_relative "is_a_validator"
5
- require_relative "kind_of_validator"
6
- require_relative "respond_to_validator"
7
- require_relative "singleton_validator"
8
-
9
- require_relative "bool_validator"
10
- require_relative "email_validator"
11
- require_relative "persisted_validator"
12
- require_relative "uuid_validator"
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class BoolValidator < ActiveModel::EachValidator
4
- def validate_each(obj, attribute, value)
5
- return if value == true || value == false
6
-
7
- obj.errors.add attribute, (options[:message] || "is not a boolean")
8
- end
9
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "kind_of_validator"
4
-
5
- class IsAValidator < KindOfValidator
6
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class PersistedValidator < ActiveModel::EachValidator
4
- def validate_each(record, attribute, value)
5
- return if (options[:allow_nil] && value.nil?) || value.try(:persisted?)
6
-
7
- record.errors.add(attribute, (options[:message] || "must be persisted"))
8
- end
9
- end