active_job-performs 0.3.1 → 0.3.3

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: a4395366ab43af9510f569bcc141c9404a15fd2d6da529029eedc970c7a8f886
4
- data.tar.gz: 9e239bf9a60e4e2785ae4b104f2cfd01e9b832729202f78ad9443c82046a7be6
3
+ metadata.gz: 360213ab324cae80fefcf276ecb9803ed8e4ec62166dc9eded626b67f8329b97
4
+ data.tar.gz: 92fa0c284711569f812da53e7acca9cbe15cea03aec0ccb9c2512465a7b93f39
5
5
  SHA512:
6
- metadata.gz: 678c75e3a24b9faa407b01a063c15fadefc23747489b9e55db52641298385f2632b91268ae20ef9bf4964562e36ed5b6df99d46b1384605fb0ee694e29c0ae3d
7
- data.tar.gz: 22231da5fc1856e480d00329e5a0cbf2482840d48eb2b2ea716751cbcc0d413d65169252aa8f3cc021b6f474e80f2a98912ce63bc1916ad2d2c1b29a3c7d273a
6
+ metadata.gz: 16fd7671e6eaeba29bac333597170661ca5333c3e14e3142ba910579316641dc2e2ba31f3fdd49508e5e0263a3fc67b34032e4ef61bb1b1a8dc3679a6a9ec26b
7
+ data.tar.gz: 353e3cf1bc646e32883352a2f4ebb80121987e415872ce9d0e32256fcbed7f559e66576a1ee15b71e2fec3930d54f362a5b8905cd502cac7daf4df7b618191e3
data/Gemfile.lock CHANGED
@@ -1,22 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active_job-performs (0.3.1)
4
+ active_job-performs (0.3.3)
5
5
  activejob (>= 6.1)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activejob (7.1.3.3)
11
- activesupport (= 7.1.3.3)
10
+ activejob (7.1.3.4)
11
+ activesupport (= 7.1.3.4)
12
12
  globalid (>= 0.3.6)
13
- activemodel (7.1.3.3)
14
- activesupport (= 7.1.3.3)
15
- activerecord (7.1.3.3)
16
- activemodel (= 7.1.3.3)
17
- activesupport (= 7.1.3.3)
13
+ activemodel (7.1.3.4)
14
+ activesupport (= 7.1.3.4)
15
+ activerecord (7.1.3.4)
16
+ activemodel (= 7.1.3.4)
17
+ activesupport (= 7.1.3.4)
18
18
  timeout (>= 0.4.0)
19
- activesupport (7.1.3.3)
19
+ activesupport (7.1.3.4)
20
20
  base64
21
21
  bigdecimal
22
22
  concurrent-ruby (~> 1.0, >= 1.0.2)
@@ -28,7 +28,7 @@ GEM
28
28
  tzinfo (~> 2.0)
29
29
  base64 (0.2.0)
30
30
  bigdecimal (3.1.8)
31
- concurrent-ruby (1.2.3)
31
+ concurrent-ruby (1.3.3)
32
32
  connection_pool (2.4.1)
33
33
  debug (1.9.2)
34
34
  irb (~> 1.10)
@@ -39,10 +39,10 @@ GEM
39
39
  i18n (1.14.5)
40
40
  concurrent-ruby (~> 1.0)
41
41
  io-console (0.7.2)
42
- irb (1.13.1)
42
+ irb (1.13.2)
43
43
  rdoc (>= 4.0.0)
44
44
  reline (>= 0.4.2)
45
- minitest (5.23.1)
45
+ minitest (5.24.0)
46
46
  minitest-sprint (1.2.2)
47
47
  path_expander (~> 1.1)
48
48
  mutex_m (0.2.0)
@@ -52,11 +52,11 @@ GEM
52
52
  rake (13.2.1)
53
53
  rdoc (6.7.0)
54
54
  psych (>= 4.0.0)
55
- reline (0.5.7)
55
+ reline (0.5.9)
56
56
  io-console (~> 0.5)
57
57
  sqlite3 (1.7.3-arm64-darwin)
58
58
  sqlite3 (1.7.3-x86_64-linux)
59
- stringio (3.1.0)
59
+ stringio (3.1.1)
60
60
  timeout (0.4.1)
61
61
  tzinfo (2.0.6)
62
62
  concurrent-ruby (~> 1.0)
@@ -76,4 +76,4 @@ DEPENDENCIES
76
76
  sqlite3 (~> 1.4)
77
77
 
78
78
  BUNDLED WITH
79
- 2.5.4
79
+ 2.5.14
data/README.md CHANGED
@@ -1,8 +1,85 @@
1
1
  # ActiveJob::Performs
2
2
 
3
- `ActiveJob::Performs` adds the `performs` macro to set up jobs by convention.
3
+ `ActiveJob::Performs` adds a `performs` class method to make the model + job loop vastly more conventional. You use it like this:
4
4
 
5
- ## Usage with `ActiveRecord::Base` & other `GlobalID::Identification` objects
5
+ ```ruby
6
+ class Post < ApplicationRecord
7
+ performs :publish
8
+ # Or `performs def publish`!
9
+
10
+ def publish
11
+ # Some logic to publish a post
12
+ end
13
+ end
14
+ ```
15
+
16
+ Here's what `performs` generates under the hood:
17
+
18
+ ```ruby
19
+ class Post < ApplicationRecord
20
+ class Job < ApplicationJob; end # We build a general Job class to share configuration between method jobs.
21
+
22
+ # Individual method jobs inherit from the `Post::Job` defined above.
23
+ class PublishJob < Job
24
+ # We generate the required `perform` method passing in the `post` and calling `publish` on it.
25
+ def perform(post, *, **) = post.publish(*, **)
26
+ end
27
+
28
+ # On Rails 7.1+, where `ActiveJob.perform_all_later` exists, we also generate
29
+ # a bulk method to enqueue many jobs at once. So you can do this:
30
+ #
31
+ # Post.unpublished.in_batches.each(&:publish_later_bulk)
32
+ def self.publish_later_bulk(set = all)
33
+ ActiveJob.perform_all_later set.map { PublishJob.new(_1) }
34
+ end
35
+
36
+ # We generate `publish_later` to wrap the job execution forwarding arguments and options.
37
+ def publish_later(*, **) = PublishJob.perform_later(self, *, **)
38
+
39
+ def publish
40
+ # Some logic to publish a post.
41
+ end
42
+ end
43
+ ```
44
+
45
+ ## Benefits
46
+
47
+ 1. Conventional Jobs: they'll now mostly call instance methods like `publish_later` -> `publish`.
48
+ 1. Follows Rails' internal conventions: this borrows from `ActionMailbox::InboundEmail#process_later` calling `process` and `ActionMailer::Base#deliver_later` calling `deliver`.
49
+ 1. Clarity & less guess work: the `_later` methods standardize how you call jobs throughout your app, so you can instantly tell what's happening.
50
+ 1. Less tedium: getting an instance method run in the background is just now a `performs` call with some potential configuration.
51
+ 1. Fewer files to manage: you don't have to dig up something in `app/jobs` just to learn almost nothing from the boilerplate in there.
52
+ 1. Remaining jobs stand out: `app/jobs` is way lighter, so any jobs in there that don't fit the `performs` pattern now stand out way more.
53
+ 1. More consolidated logic: sometimes Job classes house model-level logic, but now it's all the way out in `app/jobs` instead of `app/models`, huh?
54
+
55
+ > [!TIP]
56
+ > On that last point, `performs` does put more logic back within your Active Records, so if you need further encapsulation to prevent them growing too large, consider checking out [active_record-associated_object](https://github.com/kaspth/active_record-associated_object).
57
+
58
+ ### Used in production & praise from people
59
+
60
+ The https://www.rubyevents.org team uses `ActiveJob::Performs` quite a bit:
61
+
62
+ - [See `performs` calls in RubyEvents](https://github.com/search?q=repo%3Arubyevents%2Frubyevents+performs+language%3ARuby&type=code&l=Ruby)
63
+
64
+
65
+ Here's what [@claudiob](https://github.com/claudiob) had to say after using `ActiveJob::Performs`:
66
+
67
+ > I’ve been using active_job-performs for the last month and I love it love it love it!!
68
+ >
69
+ > Your thought process behind it is so thorough. I have a bunch of jobs now attached to models and my app/jobs folder… is empty!!
70
+ >
71
+ > This saves me a lot of mental hoops, I don’t have to switch between files anymore, everything is self-contained. Thank you!!!
72
+
73
+ From [@andycroll](https://github.com/andycroll) in a [writeup](https://andycroll.com/ruby/launching-usingrails) about launching [UsingRails](https://usingrails.com):
74
+
75
+ > I’ve also adopted a couple of gems—with exceptional Rails-level taste and author pedigree—that I hadn’t used in anger before, including `active_job-performs` from Kasper […]. Would recommend both.
76
+
77
+ And [@nshki](https://github.com/nshki) after trying it:
78
+
79
+ > Spent some time playing with [@kaspth](https://github.com/kaspth)'s [`ActiveRecord::AssociatedObject`](https://github.com/kaspth/active_record-associated_object) and `ActiveJob::Performs` and wow! The conventions these gems put in place help simplify a codebase drastically. I particularly love `ActiveJob::Performs`—it helped me refactor out all `ApplicationJob` classes I had and keep important context in the right domain model.
80
+
81
+ ## Usage
82
+ ### with `ActiveRecord::Base` & other `GlobalID::Identification` objects
6
83
 
7
84
  `ActiveJob::Performs` works with any object that has `include GlobalID::Identification` and responds to that interface.
8
85
 
@@ -13,7 +90,7 @@ class Post < ActiveRecord::Base
13
90
  extend ActiveJob::Performs # We technically auto-extend ActiveRecord::Base, but other object hierarchies need this.
14
91
 
15
92
  # `performs` builds a `Post::PublishJob` and routes configs over to it.
16
- performs :publish, queue_as: :important, discard_on: SomeError do
93
+ performs :publish, queue_adapter: :sidekiq, queue_as: :important, discard_on: SomeError do
17
94
  retry_on TimeoutError, wait: :polynomially_longer
18
95
  end
19
96
 
@@ -32,6 +109,7 @@ class Post < ActiveRecord::Base
32
109
 
33
110
  # Individual method jobs inherit from the `Post::Job` defined above.
34
111
  class PublishJob < Job
112
+ self.queue_adapter = :sidekiq
35
113
  queue_as :important
36
114
  discard_on SomeError
37
115
  retry_on TimeoutError, wait: :polynomially_longer
@@ -46,8 +124,12 @@ class Post < ActiveRecord::Base
46
124
  # a bulk method to enqueue many jobs at once. So you can do this:
47
125
  #
48
126
  # Post.unpublished.in_batches.each(&:publish_later_bulk)
49
- def self.publish_later_bulk
50
- ActiveJob.perform_all_later all.map { PublishJob.new(_1) }
127
+ #
128
+ # Or pass in a subset of posts as an argument:
129
+ #
130
+ # Post.publish_later_bulk Post.unpublished
131
+ def self.publish_later_bulk(set = all)
132
+ ActiveJob.perform_all_later set.map { PublishJob.new(_1) }
51
133
  end
52
134
 
53
135
  # We generate `publish_later` to wrap the job execution.
@@ -61,7 +143,10 @@ class Post < ActiveRecord::Base
61
143
  end
62
144
  ```
63
145
 
64
- We generate the `Post::Job` class above to share configuration between method level jobs. E.g. if you had a retract method that was setup very similar, you could do:
146
+ > [!NOTE]
147
+ > We prefer & call `{name}=` setter methods, but fall back to getters. That's how we support `self.queue_adapter=`, but also `queue_as` which is not configured via `queue_as=`.
148
+
149
+ We generate the `Post::Job` class above to share configuration between method level jobs. E.g. if you had a `retract` method that was setup very similar, you could do:
65
150
 
66
151
  ```ruby
67
152
  class Post < ActiveRecord::Base
@@ -184,7 +269,7 @@ end
184
269
 
185
270
  ### Usage with `ActiveRecord::AssociatedObject`
186
271
 
187
- The [`ActiveRecord::AssociatedObject`](https://github.com/kaspth/active_record-associated_object) gem also implements `GlobalID::Identification`, so you can do this too:
272
+ The [`ActiveRecord::AssociatedObject`](https://github.com/kaspth/active_record-associated_object) gem also implements `GlobalID::Identification`, so you use `performs` exactly like you would on Active Records:
188
273
 
189
274
  ```ruby
190
275
  class Post::Publisher < ActiveRecord::AssociatedObject
@@ -204,6 +289,11 @@ class Post::Publisher < ActiveRecord::AssociatedObject
204
289
  end
205
290
  ```
206
291
 
292
+ > [!NOTE]
293
+ > There's one difference with Active Record: you must pass in a set to `_later_bulk` methods. Like so:
294
+ >
295
+ > `Post::Publisher.publish_later_bulk Post::Publisher.first(10)`
296
+
207
297
  ### Passing `wait` to `performs`
208
298
 
209
299
  If there's a job you want to defer, `performs` can set it for each invocation:
@@ -230,12 +320,6 @@ class Post < ActiveRecord::Base
230
320
  end
231
321
  ```
232
322
 
233
- ### Praise from people
234
-
235
- Here's what [@nshki](https://github.com/nshki) found when they tried `ActiveJob::Performs`:
236
-
237
- > Spent some time playing with [@kaspth](https://github.com/kaspth)'s [`ActiveRecord::AssociatedObject`](https://github.com/kaspth/active_record-associated_object) and `ActiveJob::Performs` and wow! The conventions these gems put in place help simplify a codebase drastically. I particularly love `ActiveJob::Performs`—it helped me refactor out all `ApplicationJob` classes I had and keep important context in the right domain model.
238
-
239
323
  ## Installation
240
324
 
241
325
  Install the gem and add to the application's Gemfile by executing:
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveJob
4
4
  module Performs
5
- VERSION = "0.3.1"
5
+ VERSION = "0.3.3"
6
6
  end
7
7
  end
@@ -5,18 +5,14 @@ require_relative "performs/version"
5
5
  module ActiveJob; end
6
6
  module ActiveJob::Performs
7
7
  module Waiting
8
- def Proc(value)
9
- value.respond_to?(:call) ? value : proc { value }
10
- end unless Kernel.respond_to?(:Proc) # Optimistically assume Ruby gets this and it'll work fine.
8
+ attr_reader :wait, :wait_until
11
9
 
12
- def wait(value = nil)
13
- @wait = Proc(value) if value
14
- @wait
10
+ def wait=(value)
11
+ @wait = value.respond_to?(:call) ? value : proc { value }
15
12
  end
16
13
 
17
- def wait_until(value = nil)
18
- @wait_until = Proc(value) if value
19
- @wait_until
14
+ def wait_until=(value)
15
+ @wait_until = value.respond_to?(:call) ? value : proc { value }
20
16
  end
21
17
 
22
18
  def scoped_by_wait(record)
@@ -46,10 +42,10 @@ module ActiveJob::Performs
46
42
  end
47
43
  RUBY
48
44
 
49
- if ActiveJob.respond_to?(:perform_all_later) && respond_to?(:all)
45
+ if ActiveJob.respond_to?(:perform_all_later)
50
46
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
51
- def self.#{method}_later_bulk#{suffix}
52
- ActiveJob.perform_all_later all.map { #{job}.scoped_by_wait(_1).new(_1) }
47
+ def self.#{method}_later_bulk#{suffix}(set#{" = all" if respond_to?(:all)})
48
+ ActiveJob.perform_all_later set.map { #{job}.scoped_by_wait(_1).new(_1) }
53
49
  end
54
50
  RUBY
55
51
  end
@@ -69,9 +65,13 @@ module ActiveJob::Performs
69
65
  name.safe_constantize || const_set(name, Class.new(yield))
70
66
  end
71
67
 
72
- def apply_performs_to(job_class, **configs, &block)
73
- configs.each { job_class.public_send(_1, _2) }
74
- job_class.class_exec(&block) if block_given?
68
+ def apply_performs_to(job, **configs, &block)
69
+ job.class_exec(&block) if block_given?
70
+
71
+ configs.each do |name, value|
72
+ name = "#{name}=".then.find { job.respond_to? _1 } || name
73
+ job.public_send name, value
74
+ end
75
75
  end
76
76
 
77
77
  def performs_later_methods
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_job-performs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kasper Timm Hansen
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-05-27 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activejob
@@ -24,7 +23,6 @@ dependencies:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
25
  version: '6.1'
27
- description:
28
26
  email:
29
27
  - hey@kaspth.com
30
28
  executables: []
@@ -47,7 +45,6 @@ metadata:
47
45
  homepage_uri: https://github.com/kaspth/active_job-performs
48
46
  source_code_uri: https://github.com/kaspth/active_job-performs
49
47
  changelog_uri: https://github.com/kaspth/active_job-performs/blob/main/CHANGELOG.md
50
- post_install_message:
51
48
  rdoc_options: []
52
49
  require_paths:
53
50
  - lib
@@ -62,8 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
59
  - !ruby/object:Gem::Version
63
60
  version: '0'
64
61
  requirements: []
65
- rubygems_version: 3.5.10
66
- signing_key:
62
+ rubygems_version: 3.6.9
67
63
  specification_version: 4
68
64
  summary: ActiveJob::Performs adds the `performs` macro to set up jobs by convention.
69
65
  test_files: []