civil_service 2.1.0 → 2.4.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: 7852028628b07b8e1cb66afa9b93551f7b8d1c617ba3161adf20d05355e53da4
4
- data.tar.gz: 414e35fa95fadd0b904c82699958279c029bc2047f7c21b46631beed0a80ae3f
3
+ metadata.gz: 3cc309b95109e1703e10facefa160b6b3ec0d2c9cdeecc55c4d7fcca4fd3b788
4
+ data.tar.gz: bd935e564c4170b464e0fc5a577d885201c4a506f57bd5dd67ca69ceb5f5de5a
5
5
  SHA512:
6
- metadata.gz: 7752f150f11331751baf46f61c69cdf338196edc9ff5b4e86e42035c1d524c3d3bffa54d1c58a08f869b27ec05219cfe142c334a5582ed53ae4b8380e802fdd9
7
- data.tar.gz: 10c2096c1ff5e6b967969d00be432d72c6a3811dbd7bdc6ee7d4b04fbea4da52676cb0f5f1344fadb65e842f9b3b494cbe3c7ec1370c269d4f613d22dfe31888
6
+ metadata.gz: 10fbcc6182d07401c5e13580246511f9b8d9de9724bf049e21e0b343dee7b147dd2447ad1b58660488366dd892e05cfd5a2dba30dfeb2bf02d7d526117f09316
7
+ data.tar.gz: cb07f3d6487e639cac8c0645dc2b316a0ef017986e7d3bea0e0eaef66e66f37241b34d08989f2c558e737a549afba2e8d8c0dd49ca9cdc642c7af9c0d7914578
data/CHANGELOG.md CHANGED
@@ -1,12 +1,36 @@
1
+ # Version 2.4.0 - January 15, 2021
2
+
3
+ - `#call`, `#call_and_raise`, and `#call!` now accept an optional keyword parameter called `validate`. This will
4
+ skip validations if passed `false`. (`true` is the default value.)
5
+ - `#call!` now takes advantage of the `validate:` parameter internally to avoid running validations twice.
6
+
7
+ # Version 2.3.0 - April 3, 2020
8
+
9
+ - `#call!` now raises the underlying exception if the service threw an exception,
10
+ rather than hiding it inside a `CivilService::ServiceFailure`.
11
+
12
+ # Version 2.2.1 - October 4, 2019
13
+
14
+ - `CivilService::MultiResultService::MultiResult#exception` now checks the underlying exception on
15
+ the root result object, in case the service threw an exception.
16
+
17
+ # Version 2.2.0 - September 26, 2019
18
+
19
+ - Services now have a new `#call_and_raise` method, which will return a result object on failure
20
+ but will raise exceptions that are thrown inside the service call (effectively, the behavior of
21
+ `#call` in CivilService 1.0.0).
22
+ - Added a new mixin called `CivilService::MultiResultService`, which allows creating services whose
23
+ results are composed of multiple results that are aggregated together.
24
+
1
25
  # Version 2.1.0 - September 25, 2019
2
26
 
3
- * `CivilService::Result#errors` now always returns an Errors object even if it hasn't been
27
+ - `CivilService::Result#errors` now always returns an Errors object even if it hasn't been
4
28
  explicitly set.
5
29
 
6
30
  # Version 2.0.0 - June 26, 2019
7
31
 
8
- * BREAKING CHANGE: The behavior of `CivilService::Service#call` has changed when exceptions are
9
- raised inside the service. The `call` method will now catch the exception and return a failing
32
+ - BREAKING CHANGE: The behavior of `CivilService::Service#call` has changed when exceptions are
33
+ raised inside the service. The `call` method will now catch the exception and return a failing
10
34
  result object, with the exception message as an error on `:base`.
11
35
 
12
36
  The behavior of `call!` has not changed: a failing result will be raised as a
@@ -17,8 +41,9 @@
17
41
  will (almost) never raise an exception, whereas `call!` can raise an exception.
18
42
 
19
43
  The exception to this rule (pun intended, always intend your puns) is that `call` will not catch
20
- exceptions that don't inherit from `StandardError`, such as `SystemExit`. See
44
+ exceptions that don't inherit from `StandardError`, such as `SystemExit`. See
21
45
  [Honeybadger's explanation](https://www.honeybadger.io/blog/a-beginner-s-guide-to-exceptions-in-ruby/)
22
46
  of why this is a good idea.
23
- * `CivilService::Result` now has an additional attribute called `exception`, which can be used to
47
+
48
+ - `CivilService::Result` now has an additional attribute called `exception`, which can be used to
24
49
  retrieve an exception thrown inside a `call` method.
data/Gemfile.lock CHANGED
@@ -1,27 +1,26 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- civil_service (2.1.0)
4
+ civil_service (2.4.0)
5
5
  activemodel (>= 3.0.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activemodel (5.2.3)
11
- activesupport (= 5.2.3)
12
- activesupport (5.2.3)
10
+ activemodel (7.0.0)
11
+ activesupport (= 7.0.0)
12
+ activesupport (7.0.0)
13
13
  concurrent-ruby (~> 1.0, >= 1.0.2)
14
- i18n (>= 0.7, < 2)
15
- minitest (~> 5.1)
16
- tzinfo (~> 1.1)
17
- concurrent-ruby (1.1.5)
18
- i18n (1.6.0)
14
+ i18n (>= 1.6, < 2)
15
+ minitest (>= 5.1)
16
+ tzinfo (~> 2.0)
17
+ concurrent-ruby (1.1.9)
18
+ i18n (1.8.11)
19
19
  concurrent-ruby (~> 1.0)
20
20
  minitest (5.11.3)
21
- rake (10.5.0)
22
- thread_safe (0.3.6)
23
- tzinfo (1.2.5)
24
- thread_safe (~> 0.1)
21
+ rake (13.0.1)
22
+ tzinfo (2.0.4)
23
+ concurrent-ruby (~> 1.0)
25
24
 
26
25
  PLATFORMS
27
26
  ruby
@@ -30,7 +29,7 @@ DEPENDENCIES
30
29
  bundler (~> 1.16)
31
30
  civil_service!
32
31
  minitest (~> 5.0)
33
- rake (~> 10.0)
32
+ rake (~> 13.0)
34
33
 
35
34
  BUNDLED WITH
36
35
  1.17.2
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # CivilService
2
2
 
3
- [![Build Status](https://travis-ci.org/neinteractiveliterature/civil_service.svg?branch=master)](https://travis-ci.org/neinteractiveliterature/civil_service)
3
+ [![Build Status](https://travis-ci.org/actblue/civil_service.svg?branch=master)](https://travis-ci.org/actblue/civil_service)
4
4
 
5
5
  CivilService is a tiny framework for [service objects in Rails apps](https://hackernoon.com/service-objects-in-ruby-on-rails-and-you-79ca8a1c946e). With CivilService, you can use ActiveModel validations to do pre-flight checks before the service runs, and create your own result object classes to capture the results of complex operations.
6
6
 
7
- CivilService was extracted from [Intercode](https://github.com/neinteractiveliterature/intercode), a web app for convention organizers and participants.
7
+ CivilService was extracted from [Intercode](https://github.com/neinteractiveliterature/intercode), a web app for convention organizers and participants. It is now maintained by ActBlue.
8
8
 
9
9
  ## Installation
10
10
 
@@ -30,6 +30,7 @@ CivilService::Service is really a pretty tiny class. It does, however, have som
30
30
  * What's the difference between `#errors` and `#exception`? `#errors` is an instance of `ActiveModel::Errors`, whereas `#exception` is an instance of an exception class (it's only present if an exception was raised inside the service call). If an exception is raised, the service result will respond true to `#failure?`, false to `#success?`, and the exception's message will be added to `#errors`, so most of the time you can ignore `#exception` - but it's there in case you need to dig into the details.
31
31
  * Services include `ActiveModel::Validations` so they can easily do pre-flight checks. That means you can call `my_service.valid?` and `my_service.errors` just like you can for a model, and it also means that the service will fail if it's not valid.
32
32
  * In addition to `#call`, which always returns a result object, services have a `#call!` method, which will raise a `CivilService::ServiceFailure` exception if the service fails, or pass through an exception if one is raised inside the service call. This might be easier in some workflows; for example, it will cause a rollback if used inside an ActiveRecord transaction block.
33
+ * Finally, there's a third variant: `#call_and_raise`, which will re-raise any exceptions that occurred during the service execution, but will return a regular result object on failure.
33
34
 
34
35
  ## Basic example
35
36
 
@@ -87,4 +88,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
87
88
 
88
89
  ## Contributing
89
90
 
90
- Bug reports and pull requests are welcome on GitHub at https://github.com/neinteractiveliterature/civil_service.
91
+ Bug reports and pull requests are welcome on GitHub at https://github.com/actblue/civil_service.
@@ -23,6 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency "activemodel", ">= 3.0.0"
24
24
 
25
25
  spec.add_development_dependency "bundler", "~> 1.16"
26
- spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rake", "~> 13.0"
27
27
  spec.add_development_dependency "minitest", "~> 5.0"
28
28
  end
@@ -0,0 +1,44 @@
1
+ module CivilService::MultiResultService
2
+ extend ActiveSupport::Concern
3
+
4
+ class MultiResult < CivilService::Result
5
+ attr_accessor :results
6
+
7
+ def success?
8
+ (results || []).compact.all?(&:success)
9
+ end
10
+
11
+ def errors
12
+ errors = ActiveModel::Errors.new(self)
13
+ (results || []).compact.each do |result|
14
+ next if result.success?
15
+ result.errors.each do |attribute, error|
16
+ errors.add(attribute, error)
17
+ end
18
+ end
19
+ errors
20
+ end
21
+
22
+ def exception
23
+ super || (results || []).compact.map(&:exception).compact.first
24
+ end
25
+ end
26
+
27
+ def multi_result(results)
28
+ self.class.result_class.new(results: results)
29
+ end
30
+
31
+ class_methods do
32
+ def result_class=(result_class)
33
+ unless result_class <= CivilService::MultiResultService::MultiResult
34
+ raise 'In a MultiResultService, result_class must be a MultiResult'
35
+ end
36
+
37
+ @result_class = result_class
38
+ end
39
+ end
40
+
41
+ included do
42
+ self.result_class = CivilService::MultiResultService::MultiResult
43
+ end
44
+ end
@@ -12,8 +12,8 @@ class CivilService::Service
12
12
  end
13
13
  end
14
14
 
15
- def call
16
- unless self.class.validate_manually
15
+ def call(validate: true)
16
+ if validate && !self.class.validate_manually
17
17
  return failure(errors) unless valid?
18
18
  end
19
19
 
@@ -25,12 +25,21 @@ class CivilService::Service
25
25
  end
26
26
  end
27
27
 
28
- def call!
29
- unless self.class.validate_manually
28
+ def call_and_raise(validate: true)
29
+ result = call(validate: validate)
30
+ if result.exception
31
+ raise result.exception, result.exception.message, result.exception.backtrace
32
+ end
33
+
34
+ result
35
+ end
36
+
37
+ def call!(validate: true)
38
+ if validate && !self.class.validate_manually
30
39
  raise CivilService::ServiceFailure.new(self, failure(errors)) unless valid?
31
40
  end
32
41
 
33
- result = inner_call
42
+ result = call_and_raise(validate: false) # we already just did the validation step if needed
34
43
  raise CivilService::ServiceFailure.new(self, result) if result.failure?
35
44
  result
36
45
  end
@@ -1,3 +1,3 @@
1
1
  module CivilService
2
- VERSION = "2.1.0"
2
+ VERSION = '2.4.0'
3
3
  end
data/lib/civil_service.rb CHANGED
@@ -3,3 +3,4 @@ require "active_model"
3
3
  require "civil_service/result"
4
4
  require "civil_service/service_failure"
5
5
  require "civil_service/service"
6
+ require "civil_service/multi_result_service"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: civil_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nat Budin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-25 00:00:00.000000000 Z
11
+ date: 2022-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '13.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '13.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: minitest
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -88,6 +88,7 @@ files:
88
88
  - bin/setup
89
89
  - civil_service.gemspec
90
90
  - lib/civil_service.rb
91
+ - lib/civil_service/multi_result_service.rb
91
92
  - lib/civil_service/result.rb
92
93
  - lib/civil_service/service.rb
93
94
  - lib/civil_service/service_failure.rb
@@ -95,7 +96,7 @@ files:
95
96
  homepage: https://github.com/neinteractiveliterature/civil_service
96
97
  licenses: []
97
98
  metadata: {}
98
- post_install_message:
99
+ post_install_message:
99
100
  rdoc_options: []
100
101
  require_paths:
101
102
  - lib
@@ -110,8 +111,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
111
  - !ruby/object:Gem::Version
111
112
  version: '0'
112
113
  requirements: []
113
- rubygems_version: 3.0.3
114
- signing_key:
114
+ rubygems_version: 3.1.6
115
+ signing_key:
115
116
  specification_version: 4
116
117
  summary: A tiny service object framework for Rails apps
117
118
  test_files: []