interactor-contracts 0.2.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: 155341334dd614cae42bd73f08e6791280ba8481ce82fb99c1803ec6efff45b4
4
- data.tar.gz: e57c5cd09039e621a0df9bec33b6fcfc98b543b5d99eaf0caebc2aeb1069abdf
3
+ metadata.gz: 6209758247e17ba8e6ef497cf6266e864cdd0a3cc33d9755f1cce473c6ed2c29
4
+ data.tar.gz: dac680662651cdfdb9aa193158165978a03766ca88f05ac95e5768c85c7d18d4
5
5
  SHA512:
6
- metadata.gz: 67e22c927d40745bb42ffa6746e3f4685282c632e05f6fb18f266a686f5c10f2c339ddba5e98604d4718ce5bc47254654054775acc0d5af78ed55ef86e2e566b
7
- data.tar.gz: 199b4e95400eadea32fcba1cec5517d859a06fc57ebd394ebbd5a2497d2f90d56cde7fa6878ce261d7d792bea9b7262c89ede01e21fdba501a02109ae6b2f0e1
6
+ metadata.gz: 45047bfb79bb8233b12d8f91dfe730633a7cdea37e1c3e643bdd6300a5befefc2bea2f2808f4ff7321d5e37e0b16989a8e0bd5aa92a5e12be3fdc95f3b239ac8
7
+ data.tar.gz: 77e09b1dbcb20c9294c6af0c2dfac4fd84e982063c875907f46038b17e55aa0ea25f5ba134f49fc1c043fdcdc835333c87c9d8c89f5dc1e58e407a49fd4d66d7
@@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file. This projec
4
4
 
5
5
  [semver]: http://semver.org/spec/v2.0.0.html
6
6
 
7
+ ## [0.3.0] - 2019-10-09
8
+
9
+ ### Added
10
+
11
+ * [#27](https://github.com/michaelherold/interactor-contracts/pull/27): Upgrade dry-validation to 1.0 - [@vaihtovirta](https://github.com/vaihtovirta).
12
+ * [#30](https://github.com/michaelherold/interactor-contracts/pull/30): Allow setting a custom I18n backend for contract messages - [@michaelherold](https://github.com/michaelherold).
13
+
14
+ ### Changed
15
+
16
+ * [#29](https://github.com/michaelherold/interactor-contracts/pull/29): Renamed the `assures` method to `promises` and all of the internals to reflect the new naming. This is a backward-compatible change due to an alias of `assures` to `promises` - [@michaelherold](https://github.com/michaelherold), suggested by [@KelseyDH](https://github.com/KelseyDH).
17
+
18
+ ### Fixed
19
+
20
+ * [#26](https://github.com/michaelherold/interactor-contracts/pull/26): Fix bug with inheritance - [@raykov](https://github.com/raykov).
21
+
22
+ ### Miscellaneous
23
+
24
+ * [#24](https://github.com/michaelherold/interactor-contracts/pull/24): Fixed a typo in the gem specification - [@bittersweet](https://github.com/bittersweet).
25
+ * [#28](https://github.com/michaelherold/interactor-contracts/pull/28): Fixed
26
+ the Travis configuration to stop failing on JRuby builds - [@michaelherold](https://github.com/michaelherold).
27
+
7
28
  ## [0.2.0] - 2019-05-27
8
29
 
9
30
  ### Added
@@ -35,5 +56,7 @@ All notable changes to this project will be documented in this file. This projec
35
56
  * [#4](https://github.com/michaelherold/interactor-contracts/pull/4): Added Danger as a collaboration tool - [@michaelherold](https://github.com/michaelherold).
36
57
  * [#6](https://github.com/michaelherold/interactor-contracts/pull/6): Updated the README - [@michaelherold](https://github.com/michaelherold).
37
58
 
59
+ [unreleased]: https://github.com/michaelherold/interactor-contracts/compare/v0.2.0...master
60
+ [0.3.0]: https://github.com/michaelherold/interactor-contracts/compare/v0.2.0...v0.3.0
38
61
  [0.2.0]: https://github.com/michaelherold/interactor-contracts/compare/v0.1.0...v0.2.0
39
62
  [0.1.0]: https://github.com/michaelherold/interactor-contracts/tree/v0.1.0
data/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  [travis]: https://travis-ci.org/michaelherold/interactor-contracts
10
10
 
11
11
  Interactor::Contracts is an extension to the [interactor] gem that gives you
12
- the ability to specify the expectations (expected inputs) and assurances
12
+ the ability to specify the expectations (expected inputs) and promises
13
13
  (expected outputs) of your interactors.
14
14
 
15
15
  [interactor]: https://github.com/collectiveidea/interactor
@@ -33,7 +33,7 @@ Or install it yourself as:
33
33
  ## Usage
34
34
 
35
35
  Let's extend the sample `AuthenticateUser` from the Interactor examples with a
36
- contract that specifies its expectations and assurances.
36
+ contract that specifies its expectations and promises.
37
37
 
38
38
  ```ruby
39
39
  class AuthenticateUser
@@ -45,7 +45,7 @@ class AuthenticateUser
45
45
  required(:password).filled
46
46
  end
47
47
 
48
- assures do
48
+ promises do
49
49
  required(:user).filled
50
50
  required(:token).filled
51
51
  end
@@ -65,23 +65,38 @@ class AuthenticateUser
65
65
  end
66
66
  ```
67
67
 
68
+ ### Inputs: expectations
69
+
68
70
  The `expects` block defines the expectations: the expected attributes of the
69
71
  context prior to the interactor running, along with any predicates that further
70
72
  constrain the input.
71
73
 
72
- The `assures` block defines the assurances: the expected attributes of the
74
+ ### Outputs: promises
75
+
76
+ The `promises` block defines the promises: the expected attributes of the
73
77
  context after the interactor runs and successfully completes, along with any
74
- predicates the further constrain the output.
78
+ predicates the further constrain the output. Note, for backward-compatibility,
79
+ this is also available via the `assures` method.
75
80
 
76
81
  Because interactors can have transitive dependencies through the use of
77
82
  organizers, any other inputs or outputs are ignored from the perspective of
78
83
  the contract and are passed along to the outgoing (successful) context.
79
84
 
80
- Both `expects` and `assures` wrap [dry-validation], so you can use any
85
+ Both `expects` and `promises` wrap [dry-validation], so you can use any
81
86
  predicates defined in it to describe the expected inputs and outputs of your
82
87
  interactor.
83
88
 
84
- To hook into a failed expectation or assurance, you can use the `on_breach`
89
+ ### Contract failures: breaches
90
+
91
+ By default, contract failures, or breaches, behave like the example above:
92
+ breached keys are set on the failed context with their contract failures as
93
+ values. Note that you do not have to define an `on_breach` for the behavior, but
94
+ if you do this behavior will not occur.
95
+
96
+ If there are more complicated things you wish to do with contract failures, you
97
+ can define one or more breach handlers.
98
+
99
+ To hook into a failed expectation or promise, you can use the `on_breach`
85
100
  method to defined a breach handler. It should take a 1-arity block that expects
86
101
  an array of `Breach` objects. These objects have a `property` attribute that
87
102
  will give you the key that's in breach of its contract. Breaches also have a
@@ -100,8 +115,47 @@ result = AuthenticateUser.call({})
100
115
  result.failure? #=> true
101
116
  ```
102
117
 
118
+ If you would rather have your contract breaches be aggregated into, for example,
119
+ an `errors` property, you could use a breach handler like the following:
120
+
121
+ ```ruby
122
+ on_breach do |breaches|
123
+ context.fail!(errors: breaches)
124
+ end
125
+ ```
126
+
103
127
  [dry-validation]: https://github.com/dryrb/dry-validation
104
128
 
129
+ ### I18n support
130
+
131
+ You can [configure the underlying `dry-validation` contract][config] by passing
132
+ a block to the `config` method in your contract. This block will be evaluated on
133
+ the underlying configuration for the contract. For example, if you want to set
134
+ up the contract to use I18n in your Rails app, you might do something like this:
135
+
136
+ ```ruby
137
+ class MyInteractor
138
+ include Interactor
139
+ include Interactor::Contracts
140
+
141
+ config do
142
+ messages.backend = :i18n
143
+ messages.load_paths << Rails.root / 'config' / 'locales' / 'errors.yml'
144
+ messages.top_namespace = :interactor_contracts
145
+ end
146
+ end
147
+ ```
148
+
149
+ This sets up the I18n system (assuming the delicate load-order has been done in
150
+ the right way - you have to require `i18n` prior to requiring
151
+ `interactor-contracts` since we load `dry-validation` immediately) to use your
152
+ custom file. All lookups for error messages happen starting at the
153
+ `interactor_contracts` key in this example.
154
+
155
+ See [the documentation for `dry-validation`][config] for more information.
156
+
157
+ [config]: https://dry-rb.org/gems/dry-validation/1.0/configuration/
158
+
105
159
  ## Development
106
160
 
107
161
  After checking out the repo, run `bin/setup` to install dependencies. Then, run
@@ -140,7 +194,7 @@ versions:
140
194
  * Ruby 2.4
141
195
  * Ruby 2.5
142
196
  * Ruby 2.6
143
- * JRuby 9.1
197
+ * JRuby 9.2
144
198
 
145
199
  If something doesn't work on one of these versions, it's a bug.
146
200
 
@@ -1,15 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require File.expand_path('../lib/interactor/contracts/version', __FILE__)
3
+ require File.expand_path('lib/interactor/contracts/version', __dir__)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'interactor-contracts'
7
7
  spec.version = Interactor::Contracts::VERSION
8
8
  spec.authors = ['Michael Herold']
9
- spec.email = ['michael.j.herold@gmail.com']
9
+ spec.email = ['opensource@michaeljherold.com']
10
10
 
11
- spec.summary = 'Add contacts to your interactors'
12
- spec.description = 'Add contacts to your interactors'
11
+ spec.summary = 'Add contracts to your interactors'
12
+ spec.description = <<~DESC
13
+ Interactors are a pattern for structuring your business logic into units.
14
+ They have a flexible context that they pass between them, which makes them
15
+ easy-to-write, but hard-to-understand after you've written them. Much of
16
+ this confusion comes from not knowing what the interactor is supposed to
17
+ take as input and what it's expected to produce.
18
+
19
+ Enter contracts. Contracts allow you define, up front, a contract both for
20
+ the input of an interactor, known as expectations, and the output of it,
21
+ known as promises. Additionally, you can define a handler for what happens
22
+ when an interactor violates its contracts, known as a breach.
23
+
24
+ Declaring these contracts can help define your interface and make it easier
25
+ to understand how to use an interactor. They form both documentation and
26
+ validation for your business logic.
27
+ DESC
13
28
  spec.homepage = 'https://github.com/michaelherold/interactor-contracts'
14
29
  spec.license = 'MIT'
15
30
 
@@ -18,7 +33,14 @@ Gem::Specification.new do |spec|
18
33
  spec.files += Dir['lib/**/*.rb']
19
34
  spec.require_paths = ['lib']
20
35
 
21
- spec.add_dependency 'dry-validation', '~> 0.10'
36
+ spec.metadata = {
37
+ 'bug_tracker_uri' => 'https://github.com/michaelherold/interactor-contracts/issues',
38
+ 'changelog_uri' => 'https://github.com/michaelherold/interactor-contracts/blob/master/CHANGELOG.md',
39
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/interactor-contracts',
40
+ 'source_code_uri' => 'https://github.com/michaelherold/interactor-contracts'
41
+ }
42
+
43
+ spec.add_dependency 'dry-validation', '~> 1.0'
22
44
  spec.add_dependency 'interactor', '~> 3'
23
45
 
24
46
  spec.add_development_dependency 'bundler', '> 1.11'
@@ -18,7 +18,7 @@ module Interactor
18
18
  # required(:password).filled
19
19
  # end
20
20
  #
21
- # assures do
21
+ # promises do
22
22
  # required(:user).filled
23
23
  # required(:token).filled
24
24
  # end
@@ -4,35 +4,35 @@ require 'interactor/contracts/terms'
4
4
 
5
5
  module Interactor
6
6
  module Contracts
7
- # Contains the assurances, expectations, and consequences of an
7
+ # Contains the promises, expectations, and consequences of an
8
8
  # interactor's contract.
9
9
  class Contract
10
- # Instantiates a new Contract with the given contraints
10
+ # Instantiates a new Contract with the given constraints
11
11
  #
12
12
  # @example
13
13
  # Interactor::Contracts::Contract.new
14
14
  #
15
15
  # @api semipublic
16
- # @param [Terms] assurances the Contract's assurances
16
+ # @param [Terms] promises the Contract's promises
17
17
  # @param [Terms] expectations the Contract's expectations
18
18
  # @param [Array<#call>] consequences the Contract's consequences
19
19
  # rubocop:disable Metrics/LineLength
20
- def initialize(assurances: Terms.new, expectations: Terms.new, consequences: [])
21
- @assurances = assurances
20
+ def initialize(promises: Terms.new, expectations: Terms.new, consequences: [])
21
+ @promises = promises
22
22
  @consequences = consequences
23
23
  @expectations = expectations
24
24
  end
25
25
  # rubocop:enable Metrics/LineLength
26
26
 
27
- # The assurances the Contract will fulfill
27
+ # The promises the Contract will fulfill
28
28
  #
29
29
  # @example
30
30
  # contract = Interactor::Contracts::Contract.new
31
- # contract.assurances #=> <#Interactor::Contracts::Terms>
31
+ # contract.promises #=> <#Interactor::Contracts::Terms>
32
32
  #
33
33
  # @api semipublic
34
- # @return [Terms] the terms for the assurances
35
- attr_reader :assurances
34
+ # @return [Terms] the terms for the promises
35
+ attr_reader :promises
36
36
 
37
37
  # The expectations for arguments passed into the Interactor
38
38
  #
@@ -44,19 +44,19 @@ module Interactor
44
44
  # @return [Terms] the terms for the expectations
45
45
  attr_reader :expectations
46
46
 
47
- # Adds an assurance to the Contract's set of assurances
47
+ # Adds an promise to the Contract's set of promises
48
48
  #
49
49
  # @example
50
50
  # contract = Interactor::Contracts::Contract.new
51
- # contract.add_assurance do
51
+ # contract.add_promise do
52
52
  # required(:name).filled
53
53
  # end
54
54
  #
55
55
  # @api semipublic
56
- # @param [Block] term the assurance as a block of arity 0
56
+ # @param [Block] term the promise as a block of arity 0
57
57
  # @return [void]
58
- def add_assurance(&term)
59
- assurances.add(&term)
58
+ def add_promise(&term)
59
+ promises.add(&term)
60
60
  end
61
61
 
62
62
  # Adds a consequence to the Contract's set of consequences
@@ -89,6 +89,16 @@ module Interactor
89
89
  expectations.add(&term)
90
90
  end
91
91
 
92
+ # Configures the underlying contracts for the validation schemata
93
+ #
94
+ # @api private
95
+ # @private
96
+ # @return [void]
97
+ def config(&block)
98
+ promises.config(&block)
99
+ expectations.config(&block)
100
+ end
101
+
92
102
  # The consequences for the Contract
93
103
  #
94
104
  # @example
@@ -6,14 +6,14 @@ module Interactor
6
6
  module Contracts
7
7
  # Defines the class-level DSL that enables Interactor contracts.
8
8
  module DSL
9
- # Defines the assurances of an Interactor and creates an after hook
9
+ # Defines the promises of an Interactor and creates an after hook
10
10
  #
11
11
  # @example
12
12
  # class CreatePerson
13
13
  # include Interactor
14
14
  # include Interactor::Contracts
15
15
  #
16
- # assures do
16
+ # promises do
17
17
  # required(:person).filled
18
18
  # end
19
19
  #
@@ -23,11 +23,33 @@ module Interactor
23
23
  # end
24
24
  #
25
25
  # @api public
26
- # @param [Block] block the block defining the assurances
26
+ # @param [Block] block the block defining the promises
27
27
  # @return [void]
28
- def assures(&block)
29
- contract.add_assurance(&block)
30
- define_assurances_hook
28
+ def promises(&block)
29
+ contract.add_promise(&block)
30
+ define_promises_hook
31
+ end
32
+ alias assures promises
33
+
34
+ # Sends configuration set up to the underlying contracts in the terms
35
+ #
36
+ # @example
37
+ # class CreatePerson
38
+ # include Interactor
39
+ # include Interactor::Contracts
40
+ #
41
+ # config do
42
+ # messages.backend = :i18n
43
+ # messages.top_namespace = :my_app
44
+ # messages.load_paths << File.join(__dir__, '..', 'errors.yml')
45
+ # end
46
+ # end
47
+ #
48
+ # @api public
49
+ # @param [Block] block the block to execute for the underlying contracts
50
+ # @return [void]
51
+ def config(&block)
52
+ contract.config(&block)
31
53
  end
32
54
 
33
55
  # The Contract to enforce on calls to the Interactor
@@ -37,7 +59,7 @@ module Interactor
37
59
  # include Interactor
38
60
  # include Interactor::Contracts
39
61
  #
40
- # assures do
62
+ # promises do
41
63
  # required(:person).filled
42
64
  # end
43
65
  #
@@ -77,15 +99,18 @@ module Interactor
77
99
  define_expectations_hook
78
100
  end
79
101
 
80
- # Sets contract to given one and calls hooks
81
- # define_assurances_hook and define_expectations_hook
102
+ # Allows for the inheritance of contracts in subclasses
82
103
  #
83
- # @api semipublic
104
+ # @api private
84
105
  # @param [Contract] contract
85
106
  # @return [void]
86
107
  def inherit_contract(contract)
87
- @contract = contract
88
- define_assurances_hook
108
+ @contract = Contract.new(
109
+ promises: contract.promises.clone,
110
+ expectations: contract.expectations.clone,
111
+ consequences: contract.consequences.clone
112
+ )
113
+ define_promises_hook
89
114
  define_expectations_hook
90
115
  end
91
116
 
@@ -120,12 +145,12 @@ module Interactor
120
145
 
121
146
  private
122
147
 
123
- # Flags whether the assurances hook has been defined
148
+ # Flags whether the promises hook has been defined
124
149
  #
125
150
  # @api private
126
151
  # @return [TrueClass, FalseClass] true if the hook is defined
127
- attr_reader :defined_assurances_hook
128
- alias defined_assurances_hook? defined_assurances_hook
152
+ attr_reader :defined_promises_hook
153
+ alias defined_promises_hook? defined_promises_hook
129
154
 
130
155
  # Flags whether the expectations hook has been defined
131
156
  #
@@ -139,12 +164,12 @@ module Interactor
139
164
  # @api private
140
165
  # @raise [Interactor::Failure] if the input fails to meet its contract.
141
166
  # @return [void]
142
- def define_assurances_hook
143
- return if defined_assurances_hook?
167
+ def define_promises_hook
168
+ return if defined_promises_hook?
144
169
 
145
- after { enforce_contracts(contract.assurances) }
170
+ after { enforce_contracts(contract.promises) }
146
171
 
147
- @defined_assurances_hook = true
172
+ @defined_promises_hook = true
148
173
  end
149
174
 
150
175
  # Defines a before hook that validates the Interactor's input
@@ -10,7 +10,7 @@ module Interactor
10
10
  class Outcome
11
11
  extend Forwardable
12
12
 
13
- # Instantiantes a new Outcome based on the results of a Terms enforcement
13
+ # Instantiates a new Outcome based on the results of a Terms enforcement
14
14
  #
15
15
  # @api private
16
16
  # @param [Dry::Validation::Result] result
@@ -48,7 +48,7 @@ module Interactor
48
48
  # @api semipublic
49
49
  # @return [Array<Breach>] the breaches of the Terms' constraints
50
50
  def breaches
51
- BreachSet.new(result.messages(full: true).map do |property, messages|
51
+ BreachSet.new(result.errors(full: true).to_h.map do |property, messages|
52
52
  Breach.new(property, messages)
53
53
  end)
54
54
  end
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry-validation'
4
3
  require 'interactor/contracts/outcome'
5
4
 
6
5
  module Interactor
7
6
  module Contracts
8
- # The terms of a contract, either for assurances or expectations
7
+ # The terms of a contract, either for promises or expectations
9
8
  class Terms
10
9
  # Instantiates a new set of terms
11
10
  #
@@ -13,8 +12,8 @@ module Interactor
13
12
  # terms = Interactor::Contracts::Terms.new
14
13
  #
15
14
  # @api public
16
- # @param [Dry::Validation::Schema] terms the terms to start with
17
- def initialize(terms = Class.new(Dry::Validation::Schema))
15
+ # @param [Dry::Validation::Contract] terms the terms to start with
16
+ def initialize(terms = Class.new(Dry::Validation::Contract))
18
17
  @terms = terms
19
18
  end
20
19
 
@@ -30,7 +29,13 @@ module Interactor
30
29
  # @param [Block] term the term to add to the terms
31
30
  # @return [void]
32
31
  def add(&term)
33
- @terms = Dry::Validation.Schema(@terms, { build: false }, &term)
32
+ @terms = Class.new(Dry::Validation::Contract).tap do |new_terms|
33
+ new_terms.instance_variable_set(
34
+ :@config,
35
+ @terms.instance_variable_get(:@config).dup
36
+ )
37
+ new_terms.params(@terms.schema, &term)
38
+ end
34
39
  end
35
40
 
36
41
  # Validates the terms against a given context
@@ -46,8 +51,32 @@ module Interactor
46
51
  # @param [#to_h] context the context to validate the terms against
47
52
  # @return [Outcome]
48
53
  def call(context)
54
+ define_empty_schema
55
+
49
56
  Outcome.new(@terms.new.call(context.to_h))
50
57
  end
58
+
59
+ # Configures the underlying contracts within the terms
60
+ #
61
+ # @api private
62
+ # @private
63
+ # @return [void]
64
+ def config(&block)
65
+ @terms.config.instance_exec(&block)
66
+ end
67
+
68
+ private
69
+
70
+ # Defines a no-op schema as a base to extend upon
71
+ #
72
+ # This prevents the raising of a `Dry::Validation::SchemaMissingError`
73
+ # exception.
74
+ #
75
+ # @api private
76
+ # @return [void]
77
+ def define_empty_schema
78
+ @terms.params.nil? && @terms.params {}
79
+ end
51
80
  end
52
81
  end
53
82
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Interactor
4
4
  module Contracts
5
- VERSION = '0.2.0'
5
+ VERSION = '0.3.0'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interactor-contracts
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Herold
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-28 00:00:00.000000000 Z
11
+ date: 2019-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-validation
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.10'
19
+ version: '1.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: '0.10'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: interactor
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,9 +52,23 @@ dependencies:
52
52
  - - ">"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.11'
55
- description: Add contacts to your interactors
55
+ description: |
56
+ Interactors are a pattern for structuring your business logic into units.
57
+ They have a flexible context that they pass between them, which makes them
58
+ easy-to-write, but hard-to-understand after you've written them. Much of
59
+ this confusion comes from not knowing what the interactor is supposed to
60
+ take as input and what it's expected to produce.
61
+
62
+ Enter contracts. Contracts allow you define, up front, a contract both for
63
+ the input of an interactor, known as expectations, and the output of it,
64
+ known as promises. Additionally, you can define a handler for what happens
65
+ when an interactor violates its contracts, known as a breach.
66
+
67
+ Declaring these contracts can help define your interface and make it easier
68
+ to understand how to use an interactor. They form both documentation and
69
+ validation for your business logic.
56
70
  email:
57
- - michael.j.herold@gmail.com
71
+ - opensource@michaeljherold.com
58
72
  executables: []
59
73
  extensions: []
60
74
  extra_rdoc_files: []
@@ -77,7 +91,11 @@ files:
77
91
  homepage: https://github.com/michaelherold/interactor-contracts
78
92
  licenses:
79
93
  - MIT
80
- metadata: {}
94
+ metadata:
95
+ bug_tracker_uri: https://github.com/michaelherold/interactor-contracts/issues
96
+ changelog_uri: https://github.com/michaelherold/interactor-contracts/blob/master/CHANGELOG.md
97
+ documentation_uri: https://www.rubydoc.info/gems/interactor-contracts
98
+ source_code_uri: https://github.com/michaelherold/interactor-contracts
81
99
  post_install_message:
82
100
  rdoc_options: []
83
101
  require_paths:
@@ -93,8 +111,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
111
  - !ruby/object:Gem::Version
94
112
  version: '0'
95
113
  requirements: []
96
- rubygems_version: 3.0.3
114
+ rubygems_version: 3.0.6
97
115
  signing_key:
98
116
  specification_version: 4
99
- summary: Add contacts to your interactors
117
+ summary: Add contracts to your interactors
100
118
  test_files: []