interactify 0.3.0.pre.alpha.1 → 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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.ruby-version +1 -0
  4. data/Appraisals +23 -0
  5. data/CHANGELOG.md +14 -0
  6. data/README.md +33 -44
  7. data/gemfiles/.bundle/config +2 -0
  8. data/gemfiles/no_railties_no_sidekiq.gemfile +18 -0
  9. data/gemfiles/no_railties_no_sidekiq.gemfile.lock +127 -0
  10. data/gemfiles/railties_6.gemfile +14 -0
  11. data/gemfiles/railties_6.gemfile.lock +253 -0
  12. data/gemfiles/railties_6_no_sidekiq.gemfile +19 -0
  13. data/gemfiles/railties_6_no_sidekiq.gemfile.lock +159 -0
  14. data/gemfiles/railties_6_sidekiq.gemfile +20 -0
  15. data/gemfiles/railties_6_sidekiq.gemfile.lock +168 -0
  16. data/gemfiles/railties_7_no_sidekiq.gemfile +19 -0
  17. data/gemfiles/railties_7_no_sidekiq.gemfile.lock +158 -0
  18. data/gemfiles/railties_7_sidekiq.gemfile +20 -0
  19. data/gemfiles/railties_7_sidekiq.gemfile.lock +167 -0
  20. data/lib/interactify/async/job_klass.rb +63 -0
  21. data/lib/interactify/async/job_maker.rb +58 -0
  22. data/lib/interactify/async/jobable.rb +96 -0
  23. data/lib/interactify/async/null_job.rb +23 -0
  24. data/lib/interactify/configuration.rb +15 -0
  25. data/lib/interactify/contracts/call_wrapper.rb +19 -0
  26. data/lib/interactify/contracts/failure.rb +8 -0
  27. data/lib/interactify/contracts/helpers.rb +81 -0
  28. data/lib/interactify/contracts/mismatching_promise_error.rb +19 -0
  29. data/lib/interactify/contracts/promising.rb +36 -0
  30. data/lib/interactify/contracts/setup.rb +39 -0
  31. data/lib/interactify/dsl/each_chain.rb +90 -0
  32. data/lib/interactify/dsl/if_interactor.rb +81 -0
  33. data/lib/interactify/dsl/if_klass.rb +82 -0
  34. data/lib/interactify/dsl/organizer.rb +32 -0
  35. data/lib/interactify/dsl/unique_klass_name.rb +23 -0
  36. data/lib/interactify/dsl/wrapper.rb +74 -0
  37. data/lib/interactify/dsl.rb +12 -6
  38. data/lib/interactify/rspec_matchers/matchers.rb +68 -0
  39. data/lib/interactify/version.rb +1 -1
  40. data/lib/interactify/{interactor_wiring → wiring}/callable_representation.rb +2 -2
  41. data/lib/interactify/{interactor_wiring → wiring}/constants.rb +4 -4
  42. data/lib/interactify/{interactor_wiring → wiring}/error_context.rb +1 -1
  43. data/lib/interactify/{interactor_wiring → wiring}/files.rb +1 -1
  44. data/lib/interactify/{interactor_wiring.rb → wiring.rb} +5 -5
  45. data/lib/interactify.rb +58 -38
  46. metadata +48 -71
  47. data/lib/interactify/async_job_klass.rb +0 -61
  48. data/lib/interactify/call_wrapper.rb +0 -17
  49. data/lib/interactify/contract_failure.rb +0 -6
  50. data/lib/interactify/contract_helpers.rb +0 -71
  51. data/lib/interactify/each_chain.rb +0 -88
  52. data/lib/interactify/if_interactor.rb +0 -70
  53. data/lib/interactify/interactor_wrapper.rb +0 -72
  54. data/lib/interactify/job_maker.rb +0 -56
  55. data/lib/interactify/jobable.rb +0 -92
  56. data/lib/interactify/mismatching_promise_error.rb +0 -17
  57. data/lib/interactify/organizer.rb +0 -30
  58. data/lib/interactify/promising.rb +0 -34
  59. data/lib/interactify/rspec/matchers.rb +0 -67
  60. data/lib/interactify/unique_klass_name.rb +0 -21
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.alpha.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Burns
@@ -11,35 +11,21 @@ cert_chain: []
11
11
  date: 2023-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
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
14
+ name: activesupport
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
17
  - - ">="
32
18
  - !ruby/object:Gem::Version
33
- version: '0'
19
+ version: 6.0.0
34
20
  type: :runtime
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
24
  - - ">="
39
25
  - !ruby/object:Gem::Version
40
- version: '0'
26
+ version: 6.0.0
41
27
  - !ruby/object:Gem::Dependency
42
- name: rails
28
+ name: interactor
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
31
  - - ">="
@@ -53,7 +39,7 @@ dependencies:
53
39
  - !ruby/object:Gem::Version
54
40
  version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
- name: sidekiq
42
+ name: interactor-contracts
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - ">="
@@ -66,34 +52,6 @@ dependencies:
66
52
  - - ">="
67
53
  - !ruby/object:Gem::Version
68
54
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: debug
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: deep_matching
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
55
  description: |
98
56
  Adds the following to your interactor chains
99
57
  - lambda support
@@ -110,32 +68,51 @@ extra_rdoc_files: []
110
68
  files:
111
69
  - ".rspec"
112
70
  - ".rubocop.yml"
71
+ - ".ruby-version"
72
+ - Appraisals
113
73
  - CHANGELOG.md
114
74
  - LICENSE.txt
115
75
  - README.md
116
76
  - Rakefile
77
+ - gemfiles/.bundle/config
78
+ - gemfiles/no_railties_no_sidekiq.gemfile
79
+ - gemfiles/no_railties_no_sidekiq.gemfile.lock
80
+ - gemfiles/railties_6.gemfile
81
+ - gemfiles/railties_6.gemfile.lock
82
+ - gemfiles/railties_6_no_sidekiq.gemfile
83
+ - gemfiles/railties_6_no_sidekiq.gemfile.lock
84
+ - gemfiles/railties_6_sidekiq.gemfile
85
+ - gemfiles/railties_6_sidekiq.gemfile.lock
86
+ - gemfiles/railties_7_no_sidekiq.gemfile
87
+ - gemfiles/railties_7_no_sidekiq.gemfile.lock
88
+ - gemfiles/railties_7_sidekiq.gemfile
89
+ - gemfiles/railties_7_sidekiq.gemfile.lock
117
90
  - lib/interactify.rb
118
- - lib/interactify/async_job_klass.rb
119
- - lib/interactify/call_wrapper.rb
120
- - lib/interactify/contract_failure.rb
121
- - 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
122
102
  - lib/interactify/dsl.rb
123
- - lib/interactify/each_chain.rb
124
- - lib/interactify/if_interactor.rb
125
- - lib/interactify/interactor_wiring.rb
126
- - lib/interactify/interactor_wiring/callable_representation.rb
127
- - lib/interactify/interactor_wiring/constants.rb
128
- - lib/interactify/interactor_wiring/error_context.rb
129
- - lib/interactify/interactor_wiring/files.rb
130
- - lib/interactify/interactor_wrapper.rb
131
- - lib/interactify/job_maker.rb
132
- - lib/interactify/jobable.rb
133
- - lib/interactify/mismatching_promise_error.rb
134
- - lib/interactify/organizer.rb
135
- - lib/interactify/promising.rb
136
- - lib/interactify/rspec/matchers.rb
137
- - 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
138
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
139
116
  - sig/interactify.rbs
140
117
  homepage: https://github.com/markburns/interactify
141
118
  licenses:
@@ -154,14 +131,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
154
131
  requirements:
155
132
  - - ">="
156
133
  - !ruby/object:Gem::Version
157
- version: '3.2'
134
+ version: 3.1.4
158
135
  required_rubygems_version: !ruby/object:Gem::Requirement
159
136
  requirements:
160
- - - ">"
137
+ - - ">="
161
138
  - !ruby/object:Gem::Version
162
- version: 1.3.1
139
+ version: '0'
163
140
  requirements: []
164
- rubygems_version: 3.4.19
141
+ rubygems_version: 3.3.26
165
142
  signing_key:
166
143
  specification_version: 4
167
144
  summary: Interactors with bells and whistles
@@ -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 "sidekiq"
4
- require "sidekiq/job"
5
-
6
- require "interactify/async_job_klass"
7
-
8
- module Interactify
9
- class JobMaker
10
- attr_reader :opts, :method_name, :container_klass, :klass_suffix
11
-
12
- def initialize(container_klass:, opts:, klass_suffix:, method_name: :call!)
13
- @container_klass = container_klass
14
- @opts = opts
15
- @method_name = method_name
16
- @klass_suffix = klass_suffix
17
- end
18
-
19
- concerning :JobClass do
20
- def job_klass
21
- @job_klass ||= define_job_klass
22
- end
23
-
24
- private
25
-
26
- def define_job_klass
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