flow 0.10.8 → 0.11.1

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: b52c5f113180717df9e242c75b51a80cff0ca0d246007c0adf99247f23137ede
4
- data.tar.gz: 51245f2c5609c2788c79fa5a29df9201783c0071a8671f464d42d32b381537a8
3
+ metadata.gz: a2cbf274b4eeeec407044f9e1fa36f9adbb4e764c80fcddf8341faf71e2f579a
4
+ data.tar.gz: 3ba508665ba607fdabc7fe878199133ac5d194889eb4d911ec5b22656c47ef23
5
5
  SHA512:
6
- metadata.gz: bb6a28b1fbed617b3143c2905bc6912a72b1847e54bcbfc69a26856b116a783d79b64455544d103a7c5cdcef85ffab2928aa325ea8c7b1dad5f32055f0657bea
7
- data.tar.gz: 38db040a5c7d17b287a46c739f75e16b61861005b9a0ca6b08775083372f9b479620b9f78cefe0cfa1b9cab6f8371cc239e4c6119e1f52dbdc4dbecd3fd6fe8e
6
+ metadata.gz: d18ff6721175ce0189f883775bcc0953375837248ce8645c36ef5684d70f1dd47eb74cf5449c3a1e5d9dd0957058bd73a17dbd806108d2892218d42d40434c08
7
+ data.tar.gz: 7f60552c0bde342aa962eb6afee720f5d58cfe90ab63794457219c83a63724056833a6b482e81f192ee406288dc434f47ddd3b98e59b3eca0703ba5050d55746
data/README.md CHANGED
@@ -216,12 +216,12 @@ If the `Flow` fails you can see the failures on the instance:
216
216
 
217
217
  ## Wiki
218
218
 
219
- Learn more with our wiki [Getting Started](https://github.com/Freshly/flow/wiki/Getting-Started#installation) page.
219
+ Learn more with our wiki [Getting Started](https://github.com/RubyAfterAll/flow/wiki/Getting-Started#installation) page.
220
220
 
221
221
  You also can download wiki to have offline access.
222
222
  Just simply do:
223
223
 
224
- `git clone git@github.com:Freshly/flow.wiki.git`
224
+ `git clone git@github.com:RubyAfterAll/flow.wiki.git`
225
225
 
226
226
 
227
227
  ## License
@@ -7,6 +7,8 @@ module Flow
7
7
 
8
8
  class_methods do
9
9
  def transaction_provider
10
+ raise TransactionProviderNotDefined, "must explicitly define a transaction provider if ActiveRecord is not available" unless defined?(ActiveRecord)
11
+
10
12
  ActiveRecord::Base
11
13
  end
12
14
 
@@ -10,7 +10,7 @@ require_relative "flow/trigger"
10
10
 
11
11
  # A **Flow** is a collection of procedurally executed **Operations** sharing a common **State**.
12
12
  module Flow
13
- class FlowBase < RootObject
13
+ class FlowBase < Substance::RootObject
14
14
  include Conjunction::Junction
15
15
  suffixed_with "Flow"
16
16
 
@@ -1,58 +1,56 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set"
4
+
3
5
  module Flow
4
6
  module Operation
5
7
  module Accessors
6
8
  extend ActiveSupport::Concern
7
9
 
8
10
  included do
9
- class_attribute :_state_readers, instance_writer: false, default: []
10
- class_attribute :_state_writers, instance_writer: false, default: []
11
- class_attribute :_state_accessors, instance_writer: false, default: []
11
+ class_attribute :_state_readers, instance_writer: false, default: Set.new
12
+ class_attribute :_state_writers, instance_writer: false, default: Set.new
13
+ class_attribute :_state_accessors, instance_writer: false, default: Set.new
12
14
  end
13
15
 
14
- class_methods do
16
+ module ClassMethods
15
17
  protected
16
18
 
17
- def state_reader(name)
18
- return unless _add_state_reader_tracker(name.to_sym)
19
+ def state_reader(*names, prefix: false)
20
+ names.each do |name|
21
+ delegate name, prefix: prefix, to: :state
19
22
 
20
- delegate name, to: :state
23
+ _add_state_reader_tracker(name.to_sym)
24
+ end
21
25
  end
22
26
 
23
- def state_writer(name)
24
- return unless _add_state_writer_tracker(name.to_sym)
27
+ def state_writer(*names, prefix: false)
28
+ names.each do |name|
29
+ delegate "#{name}=", prefix: prefix, to: :state
25
30
 
26
- delegate("#{name}=", to: :state)
31
+ _add_state_writer_tracker(name.to_sym)
32
+ end
27
33
  end
28
34
 
29
- def state_accessor(name)
30
- state_reader name
31
- state_writer name
35
+ def state_accessor(*names, prefix: false)
36
+ names.each do |name|
37
+ state_reader name, prefix: prefix
38
+ state_writer name, prefix: prefix
39
+ end
32
40
  end
33
41
 
34
42
  private
35
43
 
36
44
  def _add_state_reader_tracker(name)
37
- return false if _state_readers.include?(name)
38
-
39
- _add_state_accessor_tracker(name) if _state_writers.include?(name)
45
+ _state_accessors << name if _state_writers.include?(name)
40
46
  _state_readers << name
41
47
  end
42
48
 
43
49
  def _add_state_writer_tracker(name)
44
- return false if _state_writers.include?(name)
45
-
46
- _add_state_accessor_tracker(name) if _state_readers.include?(name)
50
+ _state_accessors << name if _state_readers.include?(name)
47
51
  _state_writers << name
48
52
  end
49
53
 
50
- def _add_state_accessor_tracker(name)
51
- return if _state_accessors.include?(name)
52
-
53
- _state_accessors << name
54
- end
55
-
56
54
  def inherited(base)
57
55
  base._state_readers = _state_readers.dup
58
56
  base._state_writers = _state_writers.dup
@@ -15,7 +15,7 @@ module Flow
15
15
  class_methods do
16
16
  def state_proxy_class
17
17
  @state_proxy_class ||= Class.new(StateProxy).tap do |proxy_class|
18
- delegate_method_names = _state_writers.map { |method_name| "#{method_name}=" } + _state_readers
18
+ delegate_method_names = _state_writers.map { |method_name| "#{method_name}=" } + _state_readers.to_a
19
19
  proxy_class.delegate(*delegate_method_names, to: :_state) if delegate_method_names.any?
20
20
  end
21
21
  end
@@ -11,7 +11,7 @@ require_relative "operation/transactions"
11
11
 
12
12
  # An **Operation** is a service object which is executed with a **State**.
13
13
  module Flow
14
- class OperationBase < RootObject
14
+ class OperationBase < Substance::RootObject
15
15
  include TransactionWrapper
16
16
  include Operation::Accessors
17
17
  include Operation::Callbacks
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Stubs a given flow to always fail when triggered.
4
+ #
5
+ # Usage:
6
+ # describe SomeFlow do
7
+ # let(:flow) { described_class.new(some: :arguments) }
8
+ #
9
+ # include_context "with invalid state"
10
+ #
11
+ # before { flow.trigger }
12
+ #
13
+ # it "is failed" do
14
+ # expect(flow).not_to be_successful
15
+ # expect(flow.state.errors).to be_present
16
+ # end
17
+ # end
18
+ #
19
+ # Requires let variables to be defined in the inclusion context:
20
+ # * invalid_state_class - the state class that will be used for the flow
21
+ # * expected_state_errors - a hash in the form of:
22
+ # { attribute_name: :error_key
23
+ # # or:
24
+ # another_attributee: "error message!"
25
+ # }
26
+ RSpec.shared_context "with invalid state" do
27
+ before do
28
+ allow(invalid_state_class).to receive(:new).and_wrap_original do |mtd, **kwargs|
29
+ mtd.call(**kwargs).tap do |state|
30
+ allow(state).to receive(:run_validations!).and_wrap_original do |run_validations|
31
+ run_validations.call
32
+
33
+ expected_state_errors.each do |attr, error|
34
+ state.errors.add(attr, error)
35
+ end
36
+
37
+ false
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "shared_contexts/with_failing_operation"
4
+ require_relative "shared_contexts/with_invalid_state"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "spicerack/spec_helper"
3
+ require "substance/rspec"
4
4
 
5
5
  require_relative "rspec/custom_matchers"
6
6
  require_relative "rspec/shared_contexts"
@@ -1,15 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "state/status"
4
- require_relative "state/output"
5
-
6
3
  # A **State** is an aggregation of input and derived data.
7
4
  module Flow
8
- class StateBase < InputModel
5
+ class StateBase < Substance::OutputObject
9
6
  include Conjunction::Junction
10
7
  suffixed_with "State"
11
-
12
- include State::Status
13
- include State::Output
14
8
  end
15
9
  end
@@ -13,7 +13,7 @@ module Flow
13
13
 
14
14
  ActiveSupport::Deprecation.warn(
15
15
  "Direct state access of `#{method_name}' on #{_state.inspect} will be removed in a future version of flow. "\
16
- "Use a state accessor instead - for more information see github/freshly/flow/deprecation_notice"
16
+ "Use a state accessor instead - for more information see github/RubyAfterAll/flow/deprecation_notice"
17
17
  )
18
18
  _state.public_send(method_name, *arguments, &block)
19
19
  end
data/lib/flow/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flow
4
- VERSION = "0.10.8"
4
+ VERSION = "0.11.1"
5
5
  end
data/lib/flow.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_model"
4
- require "active_record"
5
4
  require "active_support"
6
5
 
7
- require "spicerack"
6
+ require "conjunction"
8
7
  require "malfunction"
8
+ require "substance"
9
9
 
10
10
  require_relative "flow/version"
11
11
 
@@ -15,10 +15,6 @@ require_relative "flow/concerns/transaction_wrapper"
15
15
 
16
16
  require_relative "flow/malfunction/base"
17
17
 
18
- # TODO: Remove inheritance nonsense, just use Substance once deprecation is removed from Spicerack
19
- class Flow::RootObject < (defined?(Substance::RootObject) ? Substance::RootObject : Spicerack::RootObject); end
20
- class Flow::InputModel < (defined?(Substance::InputModel) ? Substance::InputModel : Spicerack::InputModel); end
21
-
22
18
  require_relative "flow/flow_base"
23
19
  require_relative "flow/operation_base"
24
20
  require_relative "flow/state_base"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.8
4
+ version: 0.11.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Garside
@@ -9,10 +9,10 @@ authors:
9
9
  - Jordan Minneti
10
10
  - Vinod Lala
11
11
  - Andrew Cross
12
- autorequire:
12
+ autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2021-06-03 00:00:00.000000000 Z
15
+ date: 2022-03-26 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activemodel
@@ -29,7 +29,7 @@ dependencies:
29
29
  - !ruby/object:Gem::Version
30
30
  version: 5.2.1
31
31
  - !ruby/object:Gem::Dependency
32
- name: activerecord
32
+ name: activesupport
33
33
  requirement: !ruby/object:Gem::Requirement
34
34
  requirements:
35
35
  - - ">="
@@ -43,21 +43,27 @@ dependencies:
43
43
  - !ruby/object:Gem::Version
44
44
  version: 5.2.1
45
45
  - !ruby/object:Gem::Dependency
46
- name: activesupport
46
+ name: conjunction
47
47
  requirement: !ruby/object:Gem::Requirement
48
48
  requirements:
49
49
  - - ">="
50
50
  - !ruby/object:Gem::Version
51
- version: 5.2.1
51
+ version: 0.2.0
52
+ - - "<"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
52
55
  type: :runtime
53
56
  prerelease: false
54
57
  version_requirements: !ruby/object:Gem::Requirement
55
58
  requirements:
56
59
  - - ">="
57
60
  - !ruby/object:Gem::Version
58
- version: 5.2.1
61
+ version: 0.2.0
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '1.0'
59
65
  - !ruby/object:Gem::Dependency
60
- name: spicerack
66
+ name: short_circu_it
61
67
  requirement: !ruby/object:Gem::Requirement
62
68
  requirements:
63
69
  - - ">="
@@ -77,12 +83,12 @@ dependencies:
77
83
  - !ruby/object:Gem::Version
78
84
  version: '1.0'
79
85
  - !ruby/object:Gem::Dependency
80
- name: short_circu_it
86
+ name: substance
81
87
  requirement: !ruby/object:Gem::Requirement
82
88
  requirements:
83
89
  - - ">="
84
90
  - !ruby/object:Gem::Version
85
- version: 0.2.0
91
+ version: 0.26.0
86
92
  - - "<"
87
93
  - !ruby/object:Gem::Version
88
94
  version: '1.0'
@@ -92,7 +98,7 @@ dependencies:
92
98
  requirements:
93
99
  - - ">="
94
100
  - !ruby/object:Gem::Version
95
- version: 0.2.0
101
+ version: 0.26.0
96
102
  - - "<"
97
103
  - !ruby/object:Gem::Version
98
104
  version: '1.0'
@@ -136,6 +142,20 @@ dependencies:
136
142
  - - "<"
137
143
  - !ruby/object:Gem::Version
138
144
  version: '1.0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: activerecord
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: 5.2.1
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: 5.2.1
139
159
  - !ruby/object:Gem::Dependency
140
160
  name: bundler
141
161
  requirement: !ruby/object:Gem::Requirement
@@ -224,16 +244,16 @@ dependencies:
224
244
  name: shoulda-matchers
225
245
  requirement: !ruby/object:Gem::Requirement
226
246
  requirements:
227
- - - '='
247
+ - - "~>"
228
248
  - !ruby/object:Gem::Version
229
- version: 4.0.1
249
+ version: '4.0'
230
250
  type: :development
231
251
  prerelease: false
232
252
  version_requirements: !ruby/object:Gem::Requirement
233
253
  requirements:
234
- - - '='
254
+ - - "~>"
235
255
  - !ruby/object:Gem::Version
236
- version: 4.0.1
256
+ version: '4.0'
237
257
  - !ruby/object:Gem::Dependency
238
258
  name: rspice
239
259
  requirement: !ruby/object:Gem::Requirement
@@ -318,10 +338,9 @@ files:
318
338
  - lib/flow/rspec/custom_matchers/write_state.rb
319
339
  - lib/flow/rspec/shared_contexts.rb
320
340
  - lib/flow/rspec/shared_contexts/with_failing_operation.rb
341
+ - lib/flow/rspec/shared_contexts/with_invalid_state.rb
321
342
  - lib/flow/rspec/shoulda_matcher_helper.rb
322
343
  - lib/flow/spec_helper.rb
323
- - lib/flow/state/output.rb
324
- - lib/flow/state/status.rb
325
344
  - lib/flow/state_base.rb
326
345
  - lib/flow/state_proxy.rb
327
346
  - lib/flow/version.rb
@@ -363,11 +382,11 @@ files:
363
382
  - lib/generators/rspec/state/USAGE
364
383
  - lib/generators/rspec/state/state_generator.rb
365
384
  - lib/generators/rspec/state/templates/state_spec.rb.erb
366
- homepage: https://github.com/Freshly/flow
385
+ homepage: https://github.com/RubyAfterAll/flow
367
386
  licenses:
368
387
  - MIT
369
388
  metadata: {}
370
- post_install_message:
389
+ post_install_message:
371
390
  rdoc_options: []
372
391
  require_paths:
373
392
  - lib
@@ -382,8 +401,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
382
401
  - !ruby/object:Gem::Version
383
402
  version: '0'
384
403
  requirements: []
385
- rubygems_version: 3.2.17
386
- signing_key:
404
+ rubygems_version: 3.3.9
405
+ signing_key:
387
406
  specification_version: 4
388
407
  summary: Write modular and reusable business logic that's understandable and maintainable.
389
408
  test_files: []
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Output data is created by Operations during runtime and CANNOT be validated or provided as part of the input.
4
- module Flow
5
- module State
6
- module Output
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- class_attribute :_outputs, instance_writer: false, default: []
11
-
12
- delegate :_outputs, to: :class
13
-
14
- after_validation do
15
- next unless validated?
16
-
17
- _outputs.each do |key|
18
- public_send("#{key}=".to_sym, _defaults[key].value) if _defaults.key?(key) && public_send(key).nil?
19
- end
20
- end
21
- end
22
-
23
- class_methods do
24
- def inherited(base)
25
- base._outputs = _outputs.dup
26
- super
27
- end
28
-
29
- private
30
-
31
- def output(output, default: nil, &block)
32
- _outputs << output
33
- define_attribute output
34
- define_default output, static: default, &block
35
- ensure_validation_before output
36
- ensure_validation_before "#{output}=".to_sym
37
- end
38
-
39
- def ensure_validation_before(method)
40
- around_method method do |*arguments|
41
- raise NotValidatedError unless validated?
42
-
43
- super(*arguments)
44
- end
45
- end
46
- end
47
-
48
- def outputs
49
- return {} if _outputs.empty?
50
-
51
- output_struct.new(*_outputs.map(&method(:public_send)))
52
- end
53
-
54
- def output_struct
55
- Struct.new(*_outputs)
56
- end
57
- end
58
- end
59
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # The State status is used to ensure and enforce internal consistency.
4
- module Flow
5
- module State
6
- module Status
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- after_validation { self.was_validated = errors.empty? }
11
-
12
- private
13
-
14
- attr_accessor :was_validated
15
- end
16
-
17
- def validated?
18
- was_validated.present?
19
- end
20
- end
21
- end
22
- end