interactify 0.3.0.pre.RC1 → 0.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/Appraisals +2 -0
  4. data/CHANGELOG.md +5 -0
  5. data/README.md +10 -4
  6. data/gemfiles/no_railties_no_sidekiq.gemfile +3 -1
  7. data/gemfiles/no_railties_no_sidekiq.gemfile.lock +1 -1
  8. data/gemfiles/railties_6_no_sidekiq.gemfile +3 -1
  9. data/gemfiles/railties_6_no_sidekiq.gemfile.lock +2 -1
  10. data/gemfiles/railties_6_sidekiq.gemfile +3 -1
  11. data/gemfiles/railties_6_sidekiq.gemfile.lock +2 -1
  12. data/gemfiles/railties_7_no_sidekiq.gemfile +3 -1
  13. data/gemfiles/railties_7_no_sidekiq.gemfile.lock +2 -1
  14. data/gemfiles/railties_7_sidekiq.gemfile +3 -1
  15. data/gemfiles/railties_7_sidekiq.gemfile.lock +2 -1
  16. data/lib/interactify/async/job_klass.rb +63 -0
  17. data/lib/interactify/async/job_maker.rb +58 -0
  18. data/lib/interactify/async/jobable.rb +96 -0
  19. data/lib/interactify/async/null_job.rb +23 -0
  20. data/lib/interactify/configuration.rb +15 -0
  21. data/lib/interactify/contracts/call_wrapper.rb +19 -0
  22. data/lib/interactify/contracts/failure.rb +8 -0
  23. data/lib/interactify/contracts/helpers.rb +81 -0
  24. data/lib/interactify/contracts/mismatching_promise_error.rb +19 -0
  25. data/lib/interactify/contracts/promising.rb +36 -0
  26. data/lib/interactify/contracts/setup.rb +39 -0
  27. data/lib/interactify/dsl/each_chain.rb +90 -0
  28. data/lib/interactify/dsl/if_interactor.rb +81 -0
  29. data/lib/interactify/dsl/if_klass.rb +82 -0
  30. data/lib/interactify/dsl/organizer.rb +32 -0
  31. data/lib/interactify/dsl/unique_klass_name.rb +23 -0
  32. data/lib/interactify/dsl/wrapper.rb +74 -0
  33. data/lib/interactify/dsl.rb +12 -6
  34. data/lib/interactify/rspec_matchers/matchers.rb +68 -0
  35. data/lib/interactify/version.rb +1 -1
  36. data/lib/interactify/{interactor_wiring → wiring}/callable_representation.rb +2 -2
  37. data/lib/interactify/{interactor_wiring → wiring}/constants.rb +1 -1
  38. data/lib/interactify/{interactor_wiring → wiring}/error_context.rb +1 -1
  39. data/lib/interactify/{interactor_wiring → wiring}/files.rb +1 -1
  40. data/lib/interactify/{interactor_wiring.rb → wiring.rb} +4 -4
  41. data/lib/interactify.rb +13 -50
  42. metadata +31 -56
  43. data/lib/interactify/async_job_klass.rb +0 -61
  44. data/lib/interactify/call_wrapper.rb +0 -17
  45. data/lib/interactify/contract_failure.rb +0 -6
  46. data/lib/interactify/contract_helpers.rb +0 -71
  47. data/lib/interactify/each_chain.rb +0 -88
  48. data/lib/interactify/if_interactor.rb +0 -70
  49. data/lib/interactify/interactor_wrapper.rb +0 -72
  50. data/lib/interactify/job_maker.rb +0 -56
  51. data/lib/interactify/jobable.rb +0 -94
  52. data/lib/interactify/mismatching_promise_error.rb +0 -17
  53. data/lib/interactify/null_job.rb +0 -11
  54. data/lib/interactify/organizer.rb +0 -30
  55. data/lib/interactify/promising.rb +0 -34
  56. data/lib/interactify/rspec/matchers.rb +0 -67
  57. data/lib/interactify/unique_klass_name.rb +0 -21
data/lib/interactify.rb CHANGED
@@ -5,10 +5,11 @@ require "interactor-contracts"
5
5
  require "active_support/all"
6
6
 
7
7
  require "interactify/version"
8
- require "interactify/contract_helpers"
8
+ require "interactify/contracts/helpers"
9
+ require "interactify/contracts/promising"
9
10
  require "interactify/dsl"
10
- require "interactify/interactor_wiring"
11
- require "interactify/promising"
11
+ require "interactify/wiring"
12
+ require "interactify/configuration"
12
13
 
13
14
  module Interactify
14
15
  def self.railties_missing?
@@ -44,6 +45,11 @@ module Interactify
44
45
  end
45
46
  end
46
47
 
48
+ Interactify.instance_eval do
49
+ @sidekiq_missing = nil
50
+ @railties_missing = nil
51
+ end
52
+
47
53
  begin
48
54
  require "sidekiq"
49
55
  rescue LoadError
@@ -51,7 +57,7 @@ rescue LoadError
51
57
  end
52
58
 
53
59
  begin
54
- require 'rails/railtie'
60
+ require "rails/railtie"
55
61
  rescue LoadError
56
62
  Interactify.railties_missing!
57
63
  end
@@ -61,15 +67,7 @@ module Interactify
61
67
 
62
68
  class << self
63
69
  def validate_app(ignore: [])
64
- Interactify::InteractorWiring.new(root: Interactify.configuration.root, ignore:).validate_app
65
- end
66
-
67
- def sidekiq_missing?
68
- @sidekiq_missing
69
- end
70
-
71
- def sidekiq_missing!
72
- @sidekiq_missing = true
70
+ Interactify::Wiring.new(root: Interactify.configuration.root, ignore:).validate_app
73
71
  end
74
72
 
75
73
  def reset
@@ -110,7 +108,7 @@ module Interactify
110
108
 
111
109
  base.include Interactor::Organizer
112
110
  base.include Interactor::Contracts
113
- base.include Interactify::ContractHelpers
111
+ base.include Interactify::Contracts::Helpers
114
112
 
115
113
  # defines two classes on the receiver class
116
114
  # the first is the job class
@@ -131,45 +129,10 @@ module Interactify
131
129
  # that calls the interactor ExampleInteractor with (foo: 'bar')
132
130
  #
133
131
  # ExampleInteractor::Async.call(foo: 'bar')
134
- include Interactify::Jobable
132
+ include Interactify::Async::Jobable
135
133
  interactor_job
136
134
  end
137
135
 
138
- class_methods do
139
- def promising(*args)
140
- Promising.validate(self, *args)
141
- end
142
-
143
- def promised_keys
144
- _interactify_extract_keys(contract.promises)
145
- end
146
-
147
- def expected_keys
148
- _interactify_extract_keys(contract.expectations)
149
- end
150
-
151
- private
152
-
153
- # this is the most brittle part of the code, relying on
154
- # interactor-contracts internals
155
- # so extracted it to here so change is isolated
156
- def _interactify_extract_keys(clauses)
157
- clauses.instance_eval { @terms }.json&.rules&.keys
158
- end
159
- end
160
-
161
- class Configuration
162
- attr_writer :root
163
-
164
- def root
165
- @root ||= fallback
166
- end
167
-
168
- def fallback
169
- Rails.root / "app" if Interactify.railties?
170
- end
171
- end
172
-
173
136
  def called_klass_list
174
137
  context._called.map(&:class)
175
138
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interactify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.pre.RC1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Burns
@@ -10,34 +10,6 @@ bindir: exe
10
10
  cert_chain: []
11
11
  date: 2023-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: interactor
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: interactor-contracts
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
13
  - !ruby/object:Gem::Dependency
42
14
  name: activesupport
43
15
  requirement: !ruby/object:Gem::Requirement
@@ -53,13 +25,13 @@ dependencies:
53
25
  - !ruby/object:Gem::Version
54
26
  version: 6.0.0
55
27
  - !ruby/object:Gem::Dependency
56
- name: debug
28
+ name: interactor
57
29
  requirement: !ruby/object:Gem::Requirement
58
30
  requirements:
59
31
  - - ">="
60
32
  - !ruby/object:Gem::Version
61
33
  version: '0'
62
- type: :development
34
+ type: :runtime
63
35
  prerelease: false
64
36
  version_requirements: !ruby/object:Gem::Requirement
65
37
  requirements:
@@ -67,13 +39,13 @@ dependencies:
67
39
  - !ruby/object:Gem::Version
68
40
  version: '0'
69
41
  - !ruby/object:Gem::Dependency
70
- name: appraisal
42
+ name: interactor-contracts
71
43
  requirement: !ruby/object:Gem::Requirement
72
44
  requirements:
73
45
  - - ">="
74
46
  - !ruby/object:Gem::Version
75
47
  version: '0'
76
- type: :development
48
+ type: :runtime
77
49
  prerelease: false
78
50
  version_requirements: !ruby/object:Gem::Requirement
79
51
  requirements:
@@ -116,28 +88,31 @@ files:
116
88
  - gemfiles/railties_7_sidekiq.gemfile
117
89
  - gemfiles/railties_7_sidekiq.gemfile.lock
118
90
  - lib/interactify.rb
119
- - lib/interactify/async_job_klass.rb
120
- - lib/interactify/call_wrapper.rb
121
- - lib/interactify/contract_failure.rb
122
- - lib/interactify/contract_helpers.rb
91
+ - lib/interactify/async/job_klass.rb
92
+ - lib/interactify/async/job_maker.rb
93
+ - lib/interactify/async/jobable.rb
94
+ - lib/interactify/async/null_job.rb
95
+ - lib/interactify/configuration.rb
96
+ - lib/interactify/contracts/call_wrapper.rb
97
+ - lib/interactify/contracts/failure.rb
98
+ - lib/interactify/contracts/helpers.rb
99
+ - lib/interactify/contracts/mismatching_promise_error.rb
100
+ - lib/interactify/contracts/promising.rb
101
+ - lib/interactify/contracts/setup.rb
123
102
  - lib/interactify/dsl.rb
124
- - lib/interactify/each_chain.rb
125
- - lib/interactify/if_interactor.rb
126
- - lib/interactify/interactor_wiring.rb
127
- - lib/interactify/interactor_wiring/callable_representation.rb
128
- - lib/interactify/interactor_wiring/constants.rb
129
- - lib/interactify/interactor_wiring/error_context.rb
130
- - lib/interactify/interactor_wiring/files.rb
131
- - lib/interactify/interactor_wrapper.rb
132
- - lib/interactify/job_maker.rb
133
- - lib/interactify/jobable.rb
134
- - lib/interactify/mismatching_promise_error.rb
135
- - lib/interactify/null_job.rb
136
- - lib/interactify/organizer.rb
137
- - lib/interactify/promising.rb
138
- - lib/interactify/rspec/matchers.rb
139
- - lib/interactify/unique_klass_name.rb
103
+ - lib/interactify/dsl/each_chain.rb
104
+ - lib/interactify/dsl/if_interactor.rb
105
+ - lib/interactify/dsl/if_klass.rb
106
+ - lib/interactify/dsl/organizer.rb
107
+ - lib/interactify/dsl/unique_klass_name.rb
108
+ - lib/interactify/dsl/wrapper.rb
109
+ - lib/interactify/rspec_matchers/matchers.rb
140
110
  - lib/interactify/version.rb
111
+ - lib/interactify/wiring.rb
112
+ - lib/interactify/wiring/callable_representation.rb
113
+ - lib/interactify/wiring/constants.rb
114
+ - lib/interactify/wiring/error_context.rb
115
+ - lib/interactify/wiring/files.rb
141
116
  - sig/interactify.rbs
142
117
  homepage: https://github.com/markburns/interactify
143
118
  licenses:
@@ -156,12 +131,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
156
131
  requirements:
157
132
  - - ">="
158
133
  - !ruby/object:Gem::Version
159
- version: 2.7.8
134
+ version: 3.1.4
160
135
  required_rubygems_version: !ruby/object:Gem::Requirement
161
136
  requirements:
162
- - - ">"
137
+ - - ">="
163
138
  - !ruby/object:Gem::Version
164
- version: 1.3.1
139
+ version: '0'
165
140
  requirements: []
166
141
  rubygems_version: 3.3.26
167
142
  signing_key:
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Interactify
4
- class AsyncJobKlass
5
- attr_reader :container_klass, :klass_suffix
6
-
7
- def initialize(container_klass:, klass_suffix:)
8
- @container_klass = container_klass
9
- @klass_suffix = klass_suffix
10
- end
11
-
12
- def async_job_klass
13
- klass = Class.new do
14
- include Interactor
15
- include Interactor::Contracts
16
- end
17
-
18
- attach_call(klass)
19
- attach_call!(klass)
20
-
21
- klass
22
- end
23
-
24
- def attach_call(async_job_klass)
25
- # e.g. SomeInteractor::AsyncWithSuffix.call(foo: 'bar')
26
- async_job_klass.send(:define_singleton_method, :call) do |context|
27
- call!(context)
28
- end
29
- end
30
-
31
- def attach_call!(async_job_klass)
32
- this = self
33
-
34
- # e.g. SomeInteractor::AsyncWithSuffix.call!(foo: 'bar')
35
- async_job_klass.send(:define_singleton_method, :call!) do |context|
36
- # e.g. SomeInteractor::JobWithSuffix
37
- job_klass = this.container_klass.const_get("Job#{this.klass_suffix}")
38
-
39
- # e.g. SomeInteractor::JobWithSuffix.perform_async({foo: 'bar'})
40
- job_klass.perform_async(this.args(context))
41
- end
42
- end
43
-
44
- def args(context)
45
- args = context.to_h.stringify_keys
46
-
47
- return args unless container_klass.respond_to?(:expected_keys)
48
-
49
- restrict_to_optional_or_keys_from_contract(args)
50
- end
51
-
52
- def restrict_to_optional_or_keys_from_contract(args)
53
- keys = container_klass.expected_keys.map(&:to_s)
54
-
55
- optional = Array(container_klass.optional_attrs).map(&:to_s)
56
- keys += optional
57
-
58
- args.slice(*keys)
59
- end
60
- end
61
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Interactify
4
- module CallWrapper
5
- # https://github.com/collectiveidea/interactor/blob/57b2af9a5a5afeb2c01059c40b792485cc21b052/lib/interactor.rb#L114
6
- # Interactor#run calls Interactor#run!
7
- # https://github.com/collectiveidea/interactor/blob/57b2af9a5a5afeb2c01059c40b792485cc21b052/lib/interactor.rb#L49
8
- # Interactor.call calls Interactor.run
9
- #
10
- # The non bang methods call the bang methods and rescue
11
- def run
12
- @_interactor_called_by_non_bang_method = true
13
-
14
- super
15
- end
16
- end
17
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Interactify
4
- class ContractFailure < ::Interactor::Failure
5
- end
6
- end
@@ -1,71 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "interactify/jobable"
4
- require "interactify/call_wrapper"
5
- require "interactify/organizer"
6
- require "interactify/contract_failure"
7
-
8
- module Interactify
9
- module ContractHelpers
10
- extend ActiveSupport::Concern
11
-
12
- class_methods do
13
- def expect(*attrs, filled: true)
14
- expects do
15
- attrs.each do |attr|
16
- field = required(attr)
17
- field.filled if filled
18
- end
19
- end
20
-
21
- delegate(*attrs, to: :context)
22
- end
23
-
24
- def optional(*attrs)
25
- @optional_attrs ||= []
26
- @optional_attrs += attrs
27
-
28
- delegate(*attrs, to: :context)
29
- end
30
-
31
- attr_reader :optional_attrs
32
-
33
- def promise(*attrs, filled: true, should_delegate: true)
34
- promises do
35
- attrs.each do |attr|
36
- field = required(attr)
37
- field.filled if filled
38
- end
39
- end
40
-
41
- delegate(*attrs, to: :context) if should_delegate
42
- end
43
- end
44
-
45
- included do
46
- c = Class.new(ContractFailure)
47
- # example self is Whatever::SomeInteractor
48
- # failure class: Whatever::SomeInteractor::InteractorContractFailure
49
- const_set "InteractorContractFailure", c
50
- prepend CallWrapper
51
- include Organizer
52
-
53
- on_breach do |breaches|
54
- breaches = breaches.map { |b| { b.property => b.messages } }.inject(&:merge)
55
-
56
- Interactify.trigger_contract_breach_hook(context, breaches)
57
-
58
- if @_interactor_called_by_non_bang_method == true
59
- context.fail! contract_failures: breaches
60
- else
61
- # e.g. raises
62
- # SomeNamespace::SomeClass::ContractFailure, {whatever: 'is missing'}
63
- # but also sending the context into Sentry
64
- exception = c.new(breaches.to_json)
65
- Interactify.trigger_before_raise_hook(exception)
66
- raise exception
67
- end
68
- end
69
- end
70
- end
71
- end
@@ -1,88 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "interactify/unique_klass_name"
4
-
5
- module Interactify
6
- class EachChain
7
- attr_reader :each_loop_klasses, :plural_resource_name, :evaluating_receiver
8
-
9
- def self.attach_klass(evaluating_receiver, plural_resource_name, *each_loop_klasses)
10
- iteratable = new(each_loop_klasses, plural_resource_name, evaluating_receiver)
11
- iteratable.attach_klass
12
- end
13
-
14
- def initialize(each_loop_klasses, plural_resource_name, evaluating_receiver)
15
- @each_loop_klasses = each_loop_klasses
16
- @plural_resource_name = plural_resource_name
17
- @evaluating_receiver = evaluating_receiver
18
- end
19
-
20
- # allows us to dynamically create an interactor chain
21
- # that iterates over the packages and
22
- # uses the passed in each_loop_klasses
23
- # rubocop:disable all
24
- def klass
25
- this = self
26
-
27
- Class.new do # class SomeNamespace::EachPackage
28
- include Interactify # include Interactify
29
-
30
- expects do # expects do
31
- required(this.plural_resource_name) # required(:packages)
32
- end # end
33
-
34
- define_singleton_method(:source_location) do # def self.source_location
35
- const_source_location this.evaluating_receiver.to_s # [file, line]
36
- end # end
37
-
38
- define_method(:run!) do # def run!
39
- context.send(this.plural_resource_name).each_with_index do |resource, index|# context.packages.each_with_index do |package, index|
40
- context[this.singular_resource_name] = resource # context.package = package
41
- context[this.singular_resource_index_name] = index # context.package_index = index
42
-
43
- klasses = InteractorWrapper.wrap_many(self, this.each_loop_klasses)
44
-
45
- klasses.each do |interactor| # [A, B, C].each do |interactor|
46
- interactor.call!(context) # interactor.call!(context)
47
- end # end
48
- end # end
49
-
50
- context[this.singular_resource_name] = nil # context.package = nil
51
- context[this.singular_resource_index_name] = nil # context.package_index = nil
52
-
53
- context # context
54
- end # end
55
-
56
- define_method(:inspect) do
57
- "<#{this.namespace}::#{this.iterator_klass_name} iterates_over: #{this.each_loop_klasses.inspect}>"
58
- end
59
- end
60
- end
61
- # rubocop:enable all
62
-
63
- def attach_klass
64
- name = iterator_klass_name
65
-
66
- namespace.const_set(name, klass)
67
- namespace.const_get(name)
68
- end
69
-
70
- def namespace
71
- evaluating_receiver
72
- end
73
-
74
- def iterator_klass_name
75
- prefix = "Each#{singular_resource_name.to_s.camelize}"
76
-
77
- UniqueKlassName.for(namespace, prefix)
78
- end
79
-
80
- def singular_resource_name
81
- plural_resource_name.to_s.singularize.to_sym
82
- end
83
-
84
- def singular_resource_index_name
85
- "#{singular_resource_name}_index".to_sym
86
- end
87
- end
88
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "interactify/unique_klass_name"
4
-
5
- module Interactify
6
- class IfInteractor
7
- attr_reader :condition, :success_interactor, :failure_interactor, :evaluating_receiver
8
-
9
- def self.attach_klass(evaluating_receiver, condition, succcess_interactor, failure_interactor)
10
- ifable = new(evaluating_receiver, condition, succcess_interactor, failure_interactor)
11
- ifable.attach_klass
12
- end
13
-
14
- def initialize(evaluating_receiver, condition, succcess_interactor, failure_interactor)
15
- @evaluating_receiver = evaluating_receiver
16
- @condition = condition
17
- @success_interactor = succcess_interactor
18
- @failure_interactor = failure_interactor
19
- end
20
-
21
- # allows us to dynamically create an interactor chain
22
- # that iterates over the packages and
23
- # uses the passed in each_loop_klasses
24
- # rubocop:disable all
25
- def klass
26
- this = self
27
-
28
- Class.new do
29
- include Interactor
30
- include Interactor::Contracts
31
-
32
- expects do
33
- required(this.condition) unless this.condition.is_a?(Proc)
34
- end
35
-
36
- define_singleton_method(:source_location) do
37
- const_source_location this.evaluating_receiver.to_s # [file, line]
38
- end
39
-
40
- define_method(:run!) do
41
- result = this.condition.is_a?(Proc) ? this.condition.call(context) : context.send(this.condition)
42
- interactor = result ? this.success_interactor : this.failure_interactor
43
- interactor&.respond_to?(:call!) ? interactor.call!(context) : interactor&.call(context)
44
- end
45
-
46
- define_method(:inspect) do
47
- "<#{this.namespace}::#{this.if_klass_name} #{this.condition} ? #{this.success_interactor} : #{this.failure_interactor}>"
48
- end
49
- end
50
- end
51
- # rubocop:enable all
52
-
53
- def attach_klass
54
- name = if_klass_name
55
- namespace.const_set(name, klass)
56
- namespace.const_get(name)
57
- end
58
-
59
- def namespace
60
- evaluating_receiver
61
- end
62
-
63
- def if_klass_name
64
- prefix = condition.is_a?(Proc) ? "Proc" : condition
65
- prefix = "If#{prefix.to_s.camelize}"
66
-
67
- UniqueKlassName.for(namespace, prefix)
68
- end
69
- end
70
- end
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "interactify/unique_klass_name"
4
-
5
- module Interactify
6
- class InteractorWrapper
7
- attr_reader :organizer, :interactor
8
-
9
- def self.wrap_many(organizer, interactors)
10
- Array(interactors).map do |interactor|
11
- wrap(organizer, interactor)
12
- end
13
- end
14
-
15
- def self.wrap(organizer, interactor)
16
- new(organizer, interactor).wrap
17
- end
18
-
19
- def initialize(organizer, interactor)
20
- @organizer = organizer
21
- @interactor = interactor
22
- end
23
-
24
- def wrap
25
- case interactor
26
- when Hash
27
- wrap_conditional
28
- when Array
29
- wrap_chain
30
- when Proc
31
- wrap_proc
32
- else
33
- interactor
34
- end
35
- end
36
-
37
- def wrap_chain
38
- return self.class.wrap(organizer, interactor.first) if interactor.length == 1
39
-
40
- klass_name = UniqueKlassName.for(organizer, "Chained")
41
- organizer.chain(klass_name, *interactor.map { self.class.wrap(organizer, _1) })
42
- end
43
-
44
- def wrap_conditional
45
- raise ArgumentError, "Hash must have at least :if, and :then key" unless condition && then_do
46
-
47
- return organizer.if(condition, then_do, else_do) if else_do
48
-
49
- organizer.if(condition, then_do)
50
- end
51
-
52
- def condition = interactor[:if]
53
- def then_do = interactor[:then]
54
- def else_do = interactor[:else]
55
-
56
- def wrap_proc
57
- this = self
58
-
59
- Class.new do
60
- include Interactify
61
-
62
- define_singleton_method :wrapped do
63
- this.interactor
64
- end
65
-
66
- define_method(:call) do
67
- this.interactor.call(context)
68
- end
69
- end
70
- end
71
- end
72
- end
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "interactify/async_job_klass"
4
- require "interactify/null_job"
5
-
6
- module Interactify
7
- class JobMaker
8
- attr_reader :opts, :method_name, :container_klass, :klass_suffix
9
-
10
- def initialize(container_klass:, opts:, klass_suffix:, method_name: :call!)
11
- @container_klass = container_klass
12
- @opts = opts
13
- @method_name = method_name
14
- @klass_suffix = klass_suffix
15
- end
16
-
17
- concerning :JobClass do
18
- def job_klass
19
- @job_klass ||= define_job_klass
20
- end
21
-
22
- private
23
-
24
- def define_job_klass
25
- return NullJob if Interactify.sidekiq_missing?
26
-
27
- this = self
28
-
29
- invalid_keys = this.opts.symbolize_keys.keys - %i[queue retry dead backtrace pool tags]
30
-
31
- raise ArgumentError, "Invalid keys: #{invalid_keys}" if invalid_keys.any?
32
-
33
- build_job_klass(opts).tap do |klass|
34
- klass.const_set(:JOBABLE_OPTS, opts)
35
- klass.const_set(:JOBABLE_METHOD_NAME, method_name)
36
- end
37
- end
38
-
39
- def build_job_klass(opts)
40
- Class.new do
41
- include Sidekiq::Job
42
-
43
- sidekiq_options(opts)
44
-
45
- def perform(...)
46
- self.class.module_parent.send(self.class::JOBABLE_METHOD_NAME, ...)
47
- end
48
- end
49
- end
50
- end
51
-
52
- def async_job_klass
53
- AsyncJobKlass.new(container_klass:, klass_suffix:).async_job_klass
54
- end
55
- end
56
- end