operatic 0.6.0 → 0.7.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/.github/dependabot.yml +7 -0
- data/.github/workflows/ruby.yml +4 -8
- data/CHANGELOG.md +6 -0
- data/Gemfile +2 -0
- data/README.md +32 -16
- data/lib/operatic/data.rb +72 -0
- data/lib/operatic/result.rb +80 -72
- data/lib/operatic/version.rb +1 -1
- data/lib/operatic.rb +91 -53
- data/operatic.gemspec +3 -2
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56ef955a17eedc8782756d9a79b164662f2d558f16e2e8f48f5991d6452a30df
|
4
|
+
data.tar.gz: 660cb2d0ae5118614bcd449a8b3b06b041afe467d762bac8dbe3e10de506b2dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a432089ae7b3f71c3028bf34e278ea33553e924212bcc83bf5c02b0e3d28923e416e3f1cd054bfa664fce27343dcd76c9beec98dd88b4da2e85a625cb012e37
|
7
|
+
data.tar.gz: 271a800712179e79efcb75f1bd267e1dd12900b5eb07837a78aab4c35cffe3914e98733d08436a4cc3d52872934b07c04ae941648b70cd60eb61d0e3b6a6e030
|
data/.github/workflows/ruby.yml
CHANGED
@@ -8,20 +8,16 @@ jobs:
|
|
8
8
|
strategy:
|
9
9
|
matrix:
|
10
10
|
ruby:
|
11
|
-
- '2.5'
|
12
|
-
- '2.6'
|
13
11
|
- '2.7'
|
14
12
|
- '3.0'
|
15
13
|
- '3.1'
|
14
|
+
- '3.2'
|
15
|
+
- '3.3'
|
16
16
|
name: Ruby ${{ matrix.ruby }} RSpec
|
17
17
|
steps:
|
18
|
-
- uses: actions/checkout@
|
18
|
+
- uses: actions/checkout@v4
|
19
19
|
- uses: ruby/setup-ruby@v1
|
20
20
|
with:
|
21
21
|
bundler-cache: true
|
22
22
|
ruby-version: ${{ matrix.ruby }}
|
23
|
-
-
|
24
|
-
run: echo "::set-output name=value::**/*_gte_ruby_2_7_spec.rb"
|
25
|
-
if: matrix.ruby == '2.5' || matrix.ruby == '2.6'
|
26
|
-
id: rspec_exclude_pattern
|
27
|
-
- run: bundle exec rspec --exclude-pattern=${{ steps.rspec_exclude_pattern.outputs.value }}
|
23
|
+
- run: bundle exec rspec
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## Version 0.7.0 - 2024-05-12
|
4
|
+
|
5
|
+
- Data within an operation is now gathered on a separate `#data` object that's passed to a concrete `Operatic::Success`/`Operatic::Failure` result instance on completion. Convenience data accessors can be defined on the `Data` object (via the renamed `Operatic.data_attr`) but remain available on the result using the magic of `Result#method_missing`. <https://github.com/benpickles/operatic/pull/18>
|
6
|
+
- Require Ruby version 2.7+.
|
7
|
+
- Support pattern matching solely against a Result's data. <https://github.com/benpickles/operatic/pull/20>
|
8
|
+
|
3
9
|
## Version 0.6.0 - 2022-08-22
|
4
10
|
|
5
11
|
- Support pattern matching a Result (in Ruby 2.7+). <https://github.com/benpickles/operatic/pull/12>
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -24,7 +24,7 @@ class SayHello
|
|
24
24
|
attr_reader :name
|
25
25
|
|
26
26
|
# Declare convenience accessors on the result.
|
27
|
-
|
27
|
+
data_attr :message
|
28
28
|
|
29
29
|
def call
|
30
30
|
# Exit the method and mark the result as a failure.
|
@@ -36,12 +36,15 @@ class SayHello
|
|
36
36
|
end
|
37
37
|
|
38
38
|
result = SayHello.call(name: 'Dave')
|
39
|
+
result.class # => Operatic::Success
|
40
|
+
result.failure? # => false
|
39
41
|
result.success? # => true
|
40
42
|
result.message # => "Hello Dave"
|
41
43
|
result[:message] # => "Hello Dave"
|
42
44
|
result.to_h # => {:message=>"Hello Dave"}
|
43
45
|
|
44
46
|
result = SayHello.call
|
47
|
+
result.class # => Operatic::Failure
|
45
48
|
result.failure? # => true
|
46
49
|
result.success? # => false
|
47
50
|
result.message # => nil
|
@@ -49,17 +52,6 @@ result[:message] # => nil
|
|
49
52
|
result.to_h # => {}
|
50
53
|
```
|
51
54
|
|
52
|
-
An `Operatic::Result` also supports pattern matching in Ruby 2.7+ returning an array of `[success, data]`:
|
53
|
-
|
54
|
-
```ruby
|
55
|
-
case SayHello.call(name: 'Dave')
|
56
|
-
in [true, { message: }]
|
57
|
-
# Result is a success, do something with the `message` variable.
|
58
|
-
in [false, _]
|
59
|
-
# Result is a failure, do something else.
|
60
|
-
end
|
61
|
-
```
|
62
|
-
|
63
55
|
A Rails controller might use Operatic like this:
|
64
56
|
|
65
57
|
```ruby
|
@@ -76,15 +68,39 @@ class HellosController < ApplicationController
|
|
76
68
|
end
|
77
69
|
```
|
78
70
|
|
79
|
-
|
71
|
+
## Pattern matching
|
72
|
+
|
73
|
+
An Operatic result also supports pattern matching allowing you to match over a tuple of the result class and its data:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
case SayHello.call(name: 'Dave')
|
77
|
+
in [Operatic::Success, { message: }]
|
78
|
+
# Result is a success, do something with the `message` variable.
|
79
|
+
in [Operatic::Failure, _]
|
80
|
+
# Result is a failure, do something else.
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
Or match solely against its data:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
case SayHello.call(name: 'Dave')
|
88
|
+
in message:
|
89
|
+
# Result has the `message` key, do something with the variable.
|
90
|
+
else
|
91
|
+
# Do something else.
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
Which might be consumed in Rails like this:
|
80
96
|
|
81
97
|
```ruby
|
82
98
|
class HellosController < ApplicationController
|
83
99
|
def create
|
84
100
|
case SayHello.call(name: params[:name])
|
85
|
-
in [
|
101
|
+
in [Operatic::Success, { message: }]
|
86
102
|
render plain: message
|
87
|
-
in [
|
103
|
+
in [Operatic::Failure, _]
|
88
104
|
render :new
|
89
105
|
end
|
90
106
|
end
|
@@ -111,4 +127,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
111
127
|
|
112
128
|
## Code of Conduct
|
113
129
|
|
114
|
-
Everyone interacting in the Operatic project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/benpickles/operatic/blob/
|
130
|
+
Everyone interacting in the Operatic project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/benpickles/operatic/blob/main/CODE_OF_CONDUCT.md).
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Operatic
|
2
|
+
class Data
|
3
|
+
# Generate a subclass of {Data} with named +attrs+ accessors. This wouldn't
|
4
|
+
# normally be called directly, see {ClassMethods#data_attr} for example
|
5
|
+
# usage.
|
6
|
+
#
|
7
|
+
# @param attrs [Array<Symbol>] a list of convenience data accessors.
|
8
|
+
def self.define(*attrs)
|
9
|
+
Class.new(self) do
|
10
|
+
attrs.each do |name|
|
11
|
+
define_method name do
|
12
|
+
self[name]
|
13
|
+
end
|
14
|
+
|
15
|
+
define_method "#{name}=" do |value|
|
16
|
+
self[name] = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param kwargs [Hash<Symbol, anything>]
|
23
|
+
def initialize(**kwargs)
|
24
|
+
@data = kwargs
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return the value for +key+.
|
28
|
+
#
|
29
|
+
# @param key [Symbol]
|
30
|
+
#
|
31
|
+
# @return [anything]
|
32
|
+
def [](key)
|
33
|
+
@data[key]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Set data on the result.
|
37
|
+
#
|
38
|
+
# @param key [Symbol]
|
39
|
+
# @param value [anything]
|
40
|
+
def []=(key, value)
|
41
|
+
@data[key] = value
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [self]
|
45
|
+
def freeze
|
46
|
+
@data.freeze
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param hash [Hash<Symbol, anything>]
|
51
|
+
#
|
52
|
+
# @return [Data]
|
53
|
+
def merge(hash)
|
54
|
+
self.class.new.tap { |other|
|
55
|
+
other.set_data(@data)
|
56
|
+
other.set_data(hash)
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Hash<Symbol, anything>]
|
61
|
+
def to_h
|
62
|
+
@data
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
def set_data(data)
|
67
|
+
data.each do |key, value|
|
68
|
+
@data[key] = value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/operatic/result.rb
CHANGED
@@ -1,108 +1,116 @@
|
|
1
1
|
module Operatic
|
2
2
|
class Result
|
3
|
-
#
|
4
|
-
|
5
|
-
# example usage.
|
6
|
-
#
|
7
|
-
# @param attrs [Array<Symbol>] a list of convenience data accessors.
|
8
|
-
def self.generate(*attrs)
|
9
|
-
Class.new(self) do
|
10
|
-
attrs.each do |name|
|
11
|
-
define_method name do
|
12
|
-
@data[name]
|
13
|
-
end
|
14
|
-
|
15
|
-
define_method "#{name}=" do |value|
|
16
|
-
@data[name] = value
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
3
|
+
# @return [Data]
|
4
|
+
attr_reader :data
|
21
5
|
|
22
|
-
|
23
|
-
|
24
|
-
@
|
6
|
+
# @param data [Data]
|
7
|
+
def initialize(data)
|
8
|
+
@data = data
|
25
9
|
end
|
26
10
|
|
27
|
-
#
|
11
|
+
# Convenience proxy to read the +key+ from its {#data} object.
|
12
|
+
#
|
13
|
+
# @param key [Symbol]
|
14
|
+
#
|
15
|
+
# @return [anything]
|
28
16
|
def [](key)
|
29
|
-
|
17
|
+
data[key]
|
30
18
|
end
|
31
19
|
|
32
|
-
#
|
33
|
-
|
34
|
-
@data[key] = value
|
35
|
-
end
|
36
|
-
|
37
|
-
# Returns an array of success and data.
|
20
|
+
# Returns a tuple of self and {#to_h} allowing you to pattern match across
|
21
|
+
# both the result's status and its data.
|
38
22
|
#
|
39
23
|
# @example
|
40
|
-
#
|
24
|
+
# class SayHello
|
25
|
+
# include Operatic
|
26
|
+
#
|
27
|
+
# def call
|
28
|
+
# data[:message] = 'Hello world'
|
29
|
+
# end
|
30
|
+
# end
|
41
31
|
#
|
42
|
-
# case
|
43
|
-
# in [
|
32
|
+
# case SayHello.call
|
33
|
+
# in [Operatic::Success, { message: }]
|
44
34
|
# # Result is a success, do something with the `message` variable.
|
45
|
-
# in [
|
35
|
+
# in [Operatic::Failure, _]
|
46
36
|
# # Result is a failure, do something else.
|
47
37
|
# end
|
48
38
|
#
|
49
|
-
# @return [Array(
|
39
|
+
# @return [Array(self, Hash<Symbol, anything>)]
|
50
40
|
def deconstruct
|
51
|
-
[
|
41
|
+
[self, to_h]
|
52
42
|
end
|
53
43
|
|
54
|
-
#
|
55
|
-
# freeze the object so it cannot be modified further.
|
44
|
+
# Pattern match against the result's data via {#to_h}.
|
56
45
|
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
|
66
|
-
|
46
|
+
# @example
|
47
|
+
# class SayHello
|
48
|
+
# include Operatic
|
49
|
+
#
|
50
|
+
# def call
|
51
|
+
# data[:message] = 'Hello world'
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# case SayHello.call
|
56
|
+
# in message:
|
57
|
+
# # Result has the `message` key, do something with the variable.
|
58
|
+
# else
|
59
|
+
# # Do something else.
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# @return [Hash<Symbol, anything>]
|
63
|
+
def deconstruct_keys(keys = nil)
|
64
|
+
to_h
|
67
65
|
end
|
68
66
|
|
67
|
+
# @return [self]
|
69
68
|
def freeze
|
70
|
-
|
69
|
+
data.freeze
|
71
70
|
super
|
72
71
|
end
|
73
72
|
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
#
|
81
|
-
# *Note*: Calling {#success!} or {#failure!} more than once will raise a
|
82
|
-
# +FrozenError+.
|
83
|
-
def success!(**data)
|
84
|
-
@success = true
|
85
|
-
set_data(data)
|
86
|
-
freeze
|
73
|
+
# Forwards unknown methods to its {#data} object allowing convenience
|
74
|
+
# accessors defined via {Data.define} to be available directly on the
|
75
|
+
# {Result}.
|
76
|
+
def method_missing(name, *args, **kwargs, &block)
|
77
|
+
return data.public_send(name, *args, **kwargs, &block) if data.respond_to?(name)
|
78
|
+
super
|
87
79
|
end
|
88
80
|
|
89
|
-
def
|
90
|
-
|
81
|
+
def respond_to?(...)
|
82
|
+
super || data.respond_to?(...)
|
91
83
|
end
|
92
84
|
|
93
|
-
#
|
94
|
-
# {#success!}, {#failure!}, or convenience accessors added with {.generate}.
|
85
|
+
# Convenience proxy to {Data#to_h}.
|
95
86
|
#
|
96
87
|
# @return [Hash<Symbol, anything>]
|
97
88
|
def to_h
|
98
|
-
|
89
|
+
data.to_h
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class Success < Result
|
94
|
+
# @return [false]
|
95
|
+
def failure?
|
96
|
+
false
|
99
97
|
end
|
100
98
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
99
|
+
# @return [true]
|
100
|
+
def success?
|
101
|
+
true
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Failure < Result
|
106
|
+
# @return [true]
|
107
|
+
def failure?
|
108
|
+
true
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [false]
|
112
|
+
def success?
|
113
|
+
false
|
114
|
+
end
|
107
115
|
end
|
108
116
|
end
|
data/lib/operatic/version.rb
CHANGED
data/lib/operatic.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'operatic/data'
|
1
2
|
require 'operatic/errors'
|
2
3
|
require 'operatic/result'
|
3
4
|
require 'operatic/version'
|
@@ -9,115 +10,152 @@ module Operatic
|
|
9
10
|
end
|
10
11
|
|
11
12
|
module ClassMethods
|
12
|
-
# The main way
|
13
|
+
# The main way to call an operation. This initializes the class with the
|
14
|
+
# supplied +attrs+ keyword arguments and calls {Operatic#call} returning a
|
15
|
+
# frozen {Result} instance.
|
13
16
|
#
|
14
|
-
#
|
15
|
-
# calls {Operatic#call} returning a frozen {Result} instance.
|
17
|
+
# @param attrs [Hash<Symbol, anything>]
|
16
18
|
#
|
17
|
-
# @return [
|
19
|
+
# @return [Failure, Success]
|
18
20
|
def call(**attrs)
|
19
|
-
new(**attrs)
|
20
|
-
|
21
|
-
|
22
|
-
.freeze
|
21
|
+
operation = new(**attrs)
|
22
|
+
operation.call
|
23
|
+
operation.result || Success.new(operation.data).freeze
|
23
24
|
end
|
24
25
|
|
25
|
-
#
|
26
|
-
# {
|
27
|
-
#
|
26
|
+
# The same as {#call} but raises {FailureError} if the returned {#result} is
|
27
|
+
# a {Failure} - useful for things like background jobs, rake tasks, test
|
28
|
+
# setups, etc.
|
28
29
|
#
|
29
|
-
# @
|
30
|
+
# @param attrs [Hash<Symbol, anything>]
|
31
|
+
#
|
32
|
+
# @return [Success]
|
33
|
+
#
|
34
|
+
# @raise [FailureError] if the operation is not a {Success}
|
30
35
|
def call!(**attrs)
|
31
36
|
call(**attrs).tap { |result|
|
32
37
|
raise FailureError if result.failure?
|
33
38
|
}
|
34
39
|
end
|
35
40
|
|
36
|
-
# Define a {
|
37
|
-
# {
|
41
|
+
# Define a class-specific {Data} subclass with the named accessors added via
|
42
|
+
# {Data.define}.
|
38
43
|
#
|
39
44
|
# @example
|
40
45
|
# class SayHello
|
41
46
|
# include Operatic
|
42
47
|
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
# result_attr :message
|
48
|
+
# data_attr :message
|
46
49
|
#
|
47
50
|
# def call
|
48
|
-
# success!(message: "Hello #{name}")
|
51
|
+
# success!(message: "Hello #{@name}")
|
49
52
|
# end
|
50
53
|
# end
|
51
54
|
#
|
52
55
|
# result = SayHello.call(name: 'Dave')
|
53
|
-
# result.
|
54
|
-
# result.message
|
56
|
+
# result.class # => Operatic::Success
|
57
|
+
# result.message # => "Hello Dave"
|
58
|
+
# result[:message] # => "Hello Dave"
|
59
|
+
# result.to_h # => {:message=>"Hello Dave"}
|
55
60
|
#
|
56
61
|
# @param attrs [Array<Symbol>] a list of convenience data accessors to
|
57
62
|
# define on the {Result}.
|
58
|
-
def
|
59
|
-
@
|
63
|
+
def data_attr(*attrs)
|
64
|
+
@data_class = Data.define(*attrs)
|
60
65
|
end
|
61
66
|
|
62
|
-
|
63
|
-
|
67
|
+
# @return [Class<Data>]
|
68
|
+
def data_class
|
69
|
+
@data_class || Data
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
73
|
+
# @return [Success, Failure]
|
74
|
+
attr_reader :result
|
75
|
+
|
76
|
+
# @param attrs [Hash<Symbol, anything>]
|
67
77
|
def initialize(**attrs)
|
68
78
|
attrs.each do |key, value|
|
69
79
|
instance_variable_set("@#{key}", value)
|
70
80
|
end
|
71
81
|
end
|
72
82
|
|
73
|
-
# Override this method with your implementation. Use {#success!}
|
74
|
-
#
|
75
|
-
# data to it. Define convenience result accessors with
|
76
|
-
# {ClassMethods#result_attr}.
|
83
|
+
# Override this method with your implementation. Use {#success!}/{#failure!}
|
84
|
+
# to define the status of the result {Success}/{Failure} and attach data.
|
77
85
|
#
|
78
86
|
# @example
|
79
87
|
# class SayHello
|
80
88
|
# include Operatic
|
81
89
|
#
|
82
|
-
# attr_reader :name
|
83
|
-
#
|
84
|
-
# result_attr :message
|
85
|
-
#
|
86
90
|
# def call
|
87
|
-
# return failure! unless name
|
88
|
-
# success!(message: "Hello #{name}")
|
91
|
+
# return failure! unless @name
|
92
|
+
# success!(message: "Hello #{@name}")
|
89
93
|
# end
|
90
94
|
# end
|
91
95
|
#
|
92
96
|
# result = SayHello.call(name: 'Dave')
|
93
|
-
# result.
|
94
|
-
# result.
|
95
|
-
# result.
|
96
|
-
# result
|
97
|
+
# result.class # => Operatic::Success
|
98
|
+
# result.failure? # => false
|
99
|
+
# result.success? # => true
|
100
|
+
# result[:message] # => "Hello Dave"
|
101
|
+
# result.to_h # => {:message=>"Hello Dave"}
|
97
102
|
#
|
98
103
|
# result = SayHello.call
|
99
|
-
# result.
|
100
|
-
# result.
|
101
|
-
# result.
|
102
|
-
# result.to_h
|
104
|
+
# result.class # => Operatic::Failure
|
105
|
+
# result.failure? # => true
|
106
|
+
# result.success? # => false
|
107
|
+
# result.to_h # => {}
|
103
108
|
def call
|
104
109
|
end
|
105
110
|
|
106
|
-
#
|
107
|
-
|
108
|
-
|
111
|
+
# Any data to be communicated via the operation's result should be added to
|
112
|
+
# this {Data} object.
|
113
|
+
#
|
114
|
+
# *Note*: This will be frozen when returned from an operation.
|
115
|
+
#
|
116
|
+
# @example
|
117
|
+
# class SayHello
|
118
|
+
# include Operatic
|
119
|
+
#
|
120
|
+
# def call
|
121
|
+
# data[:message] = "Hello #{@name}"
|
122
|
+
# end
|
123
|
+
# end
|
124
|
+
#
|
125
|
+
# result = SayHello.call(name: 'Dave')
|
126
|
+
# result.data.to_h # => {:message=>"Dave"}
|
127
|
+
# result.data.frozen? # => true
|
128
|
+
#
|
129
|
+
# @return [Data]
|
130
|
+
def data
|
131
|
+
@data ||= self.class.data_class.new
|
109
132
|
end
|
110
133
|
|
111
|
-
#
|
112
|
-
#
|
134
|
+
# Mark the operation as a failure and prevent further modification to the
|
135
|
+
# operation, its result, and its data.
|
113
136
|
#
|
114
|
-
# @
|
115
|
-
|
116
|
-
|
137
|
+
# @param kwargs [Hash<Symbol, anything>]
|
138
|
+
#
|
139
|
+
# @raise [FrozenError] if called more than once
|
140
|
+
def failure!(**kwargs)
|
141
|
+
@result = Failure.new(data.merge(kwargs))
|
142
|
+
freeze
|
143
|
+
end
|
144
|
+
|
145
|
+
# @return [self]
|
146
|
+
def freeze
|
147
|
+
@result.freeze
|
148
|
+
super
|
117
149
|
end
|
118
150
|
|
119
|
-
#
|
120
|
-
|
121
|
-
|
151
|
+
# Mark the operation as a success and prevent further modification to the
|
152
|
+
# operation, its result, and its data.
|
153
|
+
#
|
154
|
+
# @param kwargs [Hash<Symbol, anything>]
|
155
|
+
#
|
156
|
+
# @raise [FrozenError] if called more than once
|
157
|
+
def success!(**kwargs)
|
158
|
+
@result = Success.new(data.merge(kwargs))
|
159
|
+
freeze
|
122
160
|
end
|
123
161
|
end
|
data/operatic.gemspec
CHANGED
@@ -14,12 +14,13 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.metadata = {
|
17
|
-
'changelog_uri' => 'https://github.com/benpickles/operatic/blob/
|
17
|
+
'changelog_uri' => 'https://github.com/benpickles/operatic/blob/main/CHANGELOG.md',
|
18
18
|
'documentation_uri' => 'https://rubydoc.info/gems/operatic',
|
19
|
+
'rubygems_mfa_required' => 'true',
|
19
20
|
'source_code_uri' => 'https://github.com/benpickles/operatic',
|
20
21
|
}
|
21
22
|
|
22
|
-
spec.required_ruby_version = '>= 2.
|
23
|
+
spec.required_ruby_version = '>= 2.7.0'
|
23
24
|
|
24
25
|
# Specify which files should be added to the gem when it is released.
|
25
26
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: operatic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Pickles
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -59,6 +59,7 @@ executables: []
|
|
59
59
|
extensions: []
|
60
60
|
extra_rdoc_files: []
|
61
61
|
files:
|
62
|
+
- ".github/dependabot.yml"
|
62
63
|
- ".github/workflows/ruby.yml"
|
63
64
|
- ".gitignore"
|
64
65
|
- ".rspec"
|
@@ -71,6 +72,7 @@ files:
|
|
71
72
|
- bin/console
|
72
73
|
- bin/setup
|
73
74
|
- lib/operatic.rb
|
75
|
+
- lib/operatic/data.rb
|
74
76
|
- lib/operatic/errors.rb
|
75
77
|
- lib/operatic/result.rb
|
76
78
|
- lib/operatic/version.rb
|
@@ -79,8 +81,9 @@ homepage: https://github.com/benpickles/operatic
|
|
79
81
|
licenses:
|
80
82
|
- MIT
|
81
83
|
metadata:
|
82
|
-
changelog_uri: https://github.com/benpickles/operatic/blob/
|
84
|
+
changelog_uri: https://github.com/benpickles/operatic/blob/main/CHANGELOG.md
|
83
85
|
documentation_uri: https://rubydoc.info/gems/operatic
|
86
|
+
rubygems_mfa_required: 'true'
|
84
87
|
source_code_uri: https://github.com/benpickles/operatic
|
85
88
|
post_install_message:
|
86
89
|
rdoc_options: []
|
@@ -90,14 +93,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
93
|
requirements:
|
91
94
|
- - ">="
|
92
95
|
- !ruby/object:Gem::Version
|
93
|
-
version: 2.
|
96
|
+
version: 2.7.0
|
94
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
98
|
requirements:
|
96
99
|
- - ">="
|
97
100
|
- !ruby/object:Gem::Version
|
98
101
|
version: '0'
|
99
102
|
requirements: []
|
100
|
-
rubygems_version: 3.
|
103
|
+
rubygems_version: 3.5.9
|
101
104
|
signing_key:
|
102
105
|
specification_version: 4
|
103
106
|
summary: A minimal standard interface for your operations
|