laters 0.1.2 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -1
- data/CLAUDE.md +30 -0
- data/README.md +39 -8
- data/Rakefile +13 -0
- data/lib/laters/concern.rb +67 -3
- data/lib/laters/instance_method_job.rb +22 -3
- data/lib/laters/version.rb +1 -1
- data/lib/laters.rb +2 -0
- metadata +30 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85e450085da66e2a32ab240a767416ee4f4c7cb04d891a4e6d4b1ec8c2febe15
|
4
|
+
data.tar.gz: 7ffc6eae552ccab18d82b24e736e4c1969fcb6aa51425c82489cea16e5cd0f79
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4930a10d29d4704bc1848100d84d035f38d560f8c9ef5985d7e3d21d9c77c3541750f845762ec311be29cafa17e294ede912c230802fb4dc5ccd3428c97913fb
|
7
|
+
data.tar.gz: 4cf150e51867955a1941a42af2df24444962d934f7fe551b8fb4380d12bd12acd3466b0c6ebf0afc51635ed3ead2bf7e238693d46c8b025225759fb8abc724ae
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,29 @@
|
|
1
|
-
#
|
1
|
+
# 0.3.0 (18-3-2025)
|
2
|
+
|
3
|
+
## New Features
|
4
|
+
- Added scheduled job support via `wait`, `wait_until`, and `priority` options
|
5
|
+
- Support ActiveJob scheduling options with the same interface as `perform_later`
|
6
|
+
|
7
|
+
## Bug Fixes and Improvements
|
8
|
+
- Fixed compatibility issues with newer Ruby and Rails versions
|
9
|
+
- Fixed DidYouMean deprecation warnings by upgrading Thor dependency
|
10
|
+
- Fixed Logger class compatibility with ActiveSupport
|
11
|
+
- Improved test suite with additional edge cases
|
12
|
+
|
13
|
+
# 0.2.0 (15-3-2025)
|
14
|
+
|
15
|
+
## Major Enhancements
|
16
|
+
- Added official support for Rails 5.0 through 8.0
|
17
|
+
- Added support for Ruby 3.0 through 3.4
|
18
|
+
- Added comprehensive YARD documentation for all methods and classes
|
19
|
+
|
20
|
+
## Improvements
|
21
|
+
- Enhanced callback support with comprehensive tests (`before_laters`, `after_laters`, `around_laters`)
|
22
|
+
- Added proper keyword arguments support throughout the codebase
|
23
|
+
- Fixed compatibility with ActiveJob in Rails 7+
|
24
|
+
- Updated Thor dependency to fix DidYouMean warnings
|
25
|
+
- Added test cases for all scheduling and parameter options
|
26
|
+
- Added time-related testing helpers to improve test reliability
|
2
27
|
|
3
28
|
# 0.1.2 (26-8-2020)
|
4
29
|
|
data/CLAUDE.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# CLAUDE.md - Laters Ruby Gem
|
2
|
+
|
3
|
+
## Build/Test Commands
|
4
|
+
- Run all tests: `bundle exec rake spec`
|
5
|
+
- Run single test: `bundle exec rspec spec/path_to_spec.rb:line_number`
|
6
|
+
- Run RuboCop lint: `bundle exec rubocop`
|
7
|
+
- Install dependencies: `bundle install`
|
8
|
+
- Test with specific Rails version: `RAILS_VERSION=7.0 bundle install && bundle exec rake`
|
9
|
+
|
10
|
+
## Code Style Guidelines
|
11
|
+
- Follow standard Ruby style conventions
|
12
|
+
- Use RuboCop 1.25+ for linting
|
13
|
+
- RSpec tests use expect syntax (not should syntax)
|
14
|
+
- Use 2 space indentation
|
15
|
+
- Private methods are grouped with `private` keyword
|
16
|
+
- Callbacks are defined after regular methods
|
17
|
+
- Class methods are defined before instance methods
|
18
|
+
- ActiveRecord models follow Rails naming conventions
|
19
|
+
- Error handling uses custom `Laters::Error` class
|
20
|
+
- Use keyword arguments in method signatures for Rails 7+ compatibility
|
21
|
+
- Documentation in README for public API features
|
22
|
+
|
23
|
+
## Project Structure
|
24
|
+
The gem follows standard Rails gem structure with:
|
25
|
+
- `lib/laters.rb` as main entry point
|
26
|
+
- ActiveRecord models include `Laters::Concern`
|
27
|
+
- Test suite uses RSpec with Combustion for Rails engine testing
|
28
|
+
- Queue configuration via `run_in_queue` class method
|
29
|
+
- Callbacks: `before_laters`, `after_laters`, `around_laters`
|
30
|
+
- Compatible with Rails 5.0 through 8 and Ruby 3.0 through 3.4
|
data/README.md
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
# Laters
|
1
|
+
# Laters 👋
|
2
|
+
[](https://badge.fury.io/rb/laters)
|
2
3
|
|
3
|
-
Run any instance_method of ActiveRecord models via a job by adding `_later` to it. Laters
|
4
|
+
Run any instance_method of ActiveRecord models via a job by adding `_later` to it. Laters, means See you later in
|
4
5
|
Dutch 🇳🇱
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
Compatible with Rails 5.0 through 8 and Ruby 3.0 through 3.4.
|
8
|
+
|
8
9
|
|
9
10
|
## Installation
|
10
11
|
|
@@ -26,7 +27,7 @@ class User < ApplicationRecord
|
|
26
27
|
include Laters::Concern
|
27
28
|
|
28
29
|
after_create_commit :notify_user_later
|
29
|
-
after_commit :
|
30
|
+
after_commit :generate_ai_summary_later
|
30
31
|
|
31
32
|
private
|
32
33
|
|
@@ -35,8 +36,18 @@ class User < ApplicationRecord
|
|
35
36
|
Sms.send(to: user.phone, message: 'Hey!')
|
36
37
|
end
|
37
38
|
|
38
|
-
def
|
39
|
-
#
|
39
|
+
def generate_ai_summary
|
40
|
+
# Call Claude API to generate a summary asynchronously
|
41
|
+
prompt = "Summarize this user profile: #{name}, #{bio}"
|
42
|
+
|
43
|
+
response = AnthropicClient.complete(
|
44
|
+
model: "claude-3-7-sonnet",
|
45
|
+
prompt: prompt,
|
46
|
+
max_tokens: 150
|
47
|
+
)
|
48
|
+
|
49
|
+
# Store the AI-generated summary
|
50
|
+
update(ai_summary: response.completion)
|
40
51
|
end
|
41
52
|
end
|
42
53
|
```
|
@@ -51,7 +62,27 @@ class User < ApplicationRecord
|
|
51
62
|
end
|
52
63
|
```
|
53
64
|
|
54
|
-
|
65
|
+
### Scheduling Options
|
66
|
+
|
67
|
+
You can use ActiveJob's scheduling options when calling methods with `_later`:
|
68
|
+
|
69
|
+
```rb
|
70
|
+
# Run 5 minutes from now
|
71
|
+
user.send_welcome_email_later(wait: 5.minutes)
|
72
|
+
|
73
|
+
# Run at a specific time
|
74
|
+
user.send_welcome_email_later(wait_until: 1.day.from_now)
|
75
|
+
|
76
|
+
# Set a priority (if supported by your queue adapter)
|
77
|
+
user.send_welcome_email_later(priority: 10)
|
78
|
+
|
79
|
+
# With method arguments
|
80
|
+
user.send_email_later('Welcome!', cc: admin@example.com, wait: 10.minutes)
|
81
|
+
```
|
82
|
+
|
83
|
+
### Callbacks
|
84
|
+
|
85
|
+
If you need callbacks, they are provided as standard model callbacks:
|
55
86
|
|
56
87
|
```rb
|
57
88
|
class User < ApplicationRecord
|
data/Rakefile
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rspec/core/rake_task"
|
3
3
|
|
4
|
+
# Silence the DidYouMean deprecation warnings
|
5
|
+
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error) && defined?(DidYouMean::SPELL_CHECKERS)
|
6
|
+
# Monkey patch DidYouMean to suppress deprecation warnings
|
7
|
+
DidYouMean::SPELL_CHECKERS.singleton_class.prepend(Module.new do
|
8
|
+
def merge!(error_name, spell_checker)
|
9
|
+
DidYouMean.correct_error(error_name, spell_checker)
|
10
|
+
end
|
11
|
+
end)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Silence URI redefinition warnings in Ruby 3.2+
|
15
|
+
$VERBOSE = nil if RUBY_VERSION >= '3.2.0'
|
16
|
+
|
4
17
|
RSpec::Core::RakeTask.new(:spec)
|
5
18
|
|
6
19
|
task :default => :spec
|
data/lib/laters/concern.rb
CHANGED
@@ -1,17 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Laters
|
4
|
+
# Main concern that provides asynchronous execution of ActiveRecord model methods
|
5
|
+
#
|
6
|
+
# This module adds the ability to defer execution of an instance method
|
7
|
+
# to a background job by calling a method with the `_later` suffix.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# class User < ActiveRecord::Base
|
11
|
+
# include Laters::Concern
|
12
|
+
#
|
13
|
+
# def send_welcome_email
|
14
|
+
# # Some long running task
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # Basic usage (executes in background)
|
19
|
+
# user.send_welcome_email_later
|
20
|
+
#
|
21
|
+
# # With scheduling options
|
22
|
+
# user.send_welcome_email_later(wait: 5.minutes)
|
23
|
+
# user.send_welcome_email_later(wait_until: 1.day.from_now)
|
24
|
+
#
|
4
25
|
module Concern
|
5
26
|
extend ActiveSupport::Concern
|
6
27
|
include ActiveModel::Callbacks
|
7
28
|
|
29
|
+
# Define laters callbacks when concern is included
|
8
30
|
included { define_model_callbacks :laters }
|
9
31
|
|
10
32
|
class_methods do
|
33
|
+
# @return [Symbol, nil] The queue name to use for background jobs
|
11
34
|
attr_reader :job_queue
|
12
35
|
|
13
36
|
private
|
14
37
|
|
38
|
+
# Configure the queue to use for background jobs
|
39
|
+
#
|
40
|
+
# @param [Symbol] queue The queue name to use for jobs
|
41
|
+
# @return [Symbol] The configured queue name
|
42
|
+
# @example
|
43
|
+
# class Comment < ActiveRecord::Base
|
44
|
+
# include Laters::Concern
|
45
|
+
# run_in_queue :low
|
46
|
+
# end
|
15
47
|
def run_in_queue(queue)
|
16
48
|
@job_queue = queue
|
17
49
|
end
|
@@ -19,21 +51,53 @@ module Laters
|
|
19
51
|
|
20
52
|
private
|
21
53
|
|
22
|
-
|
54
|
+
# Handles method calls with _later suffix by enqueueing background jobs
|
55
|
+
#
|
56
|
+
# @param [Symbol] method The method being called
|
57
|
+
# @param [Array] args Arguments to pass to the method
|
58
|
+
# @param [Hash] kwargs Keyword arguments to pass to the method
|
59
|
+
# Special kwargs for job scheduling are extracted:
|
60
|
+
# @option kwargs [Integer] :wait Time in seconds to wait before executing
|
61
|
+
# @option kwargs [Time] :wait_until Specific time to execute the job
|
62
|
+
# @option kwargs [Integer] :priority Priority for the job
|
63
|
+
# @param [Proc] block Block to pass to the method (unused)
|
64
|
+
# @return [ActiveJob::Base] The enqueued job
|
65
|
+
# @raise [NoMethodError] If the method doesn't exist
|
66
|
+
def method_missing(method, *args, **kwargs, &block)
|
23
67
|
if (method_to_call = deferrable_method_name(method))
|
68
|
+
# Extract ActiveJob options if they exist in kwargs
|
69
|
+
job_options = { queue: self.class.job_queue || :default }
|
70
|
+
|
71
|
+
# Move scheduling options from kwargs to job_options
|
72
|
+
job_options[:wait] = kwargs.delete(:wait) if kwargs.key?(:wait)
|
73
|
+
job_options[:wait_until] = kwargs.delete(:wait_until) if kwargs.key?(:wait_until)
|
74
|
+
job_options[:priority] = kwargs.delete(:priority) if kwargs.key?(:priority)
|
75
|
+
|
76
|
+
# Set all options at once
|
24
77
|
InstanceMethodJob
|
25
|
-
.set(
|
26
|
-
.perform_later(self, method_to_call, *args)
|
78
|
+
.set(job_options)
|
79
|
+
.perform_later(self, method_to_call, *args, **kwargs)
|
27
80
|
else
|
28
81
|
super
|
29
82
|
end
|
30
83
|
end
|
31
84
|
|
85
|
+
# Determines if the object responds to a method with _later suffix
|
86
|
+
#
|
87
|
+
# @param [Symbol] method_name The method name to check
|
88
|
+
# @param [Boolean] include_private Whether to include private methods
|
89
|
+
# @return [Boolean] True if the method can be handled
|
32
90
|
def respond_to_missing?(method_name, include_private = false)
|
33
91
|
method_name.to_s.ends_with?('_later') || super
|
34
92
|
end
|
35
93
|
|
94
|
+
# Extracts the actual method name from a method with _later suffix
|
95
|
+
#
|
36
96
|
# @param [Symbol] deferring_method Name of the deferring method that was called
|
97
|
+
# @return [String, nil] The actual method name to call or nil if not applicable
|
98
|
+
# @example
|
99
|
+
# deferrable_method_name(:send_email_later) # => "send_email"
|
100
|
+
# deferrable_method_name(:save_later) # => "save!" (if save! exists)
|
37
101
|
def deferrable_method_name(deferring_method)
|
38
102
|
return unless (method = deferring_method.to_s).ends_with? '_later'
|
39
103
|
|
@@ -1,15 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Laters
|
4
|
-
class
|
5
|
-
|
4
|
+
# Job class that executes deferred instance methods with callbacks
|
5
|
+
#
|
6
|
+
# This job is responsible for executing a method on an ActiveRecord object
|
7
|
+
# in the background. It runs all registered callbacks around the method execution.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # This job is automatically used by the Laters::Concern
|
11
|
+
# InstanceMethodJob.perform_later(user, "send_welcome_email", arg1, arg2)
|
12
|
+
#
|
13
|
+
class InstanceMethodJob < (Rails.application.config.respond_to?(:active_job) ?
|
14
|
+
Rails.application.config.active_job.base_job || ActiveJob::Base :
|
15
|
+
ActiveJob::Base)
|
16
|
+
# Executes the specified method on the given object
|
17
|
+
#
|
18
|
+
# @param [Object] object The object to call the method on
|
19
|
+
# @param [String] method_name The name of the method to call
|
20
|
+
# @param [Array] args Arguments to pass to the method
|
21
|
+
# @param [Hash] kwargs Keyword arguments to pass to the method
|
22
|
+
# @return [Object] The result of the method call
|
23
|
+
# @raise [Exception] Any exception raised by the method
|
24
|
+
def perform(object, method_name, *args, **kwargs)
|
6
25
|
if object.respond_to? :id
|
7
26
|
Rails.logger.info "Calling deferred #{method_name} on #{object.class} ##{object.id}"
|
8
27
|
else
|
9
28
|
Rails.logger.info "Calling deferred #{object.class}##{method_name}"
|
10
29
|
end
|
11
30
|
|
12
|
-
object.run_callbacks(:laters) { object.send(method_name, *args) }
|
31
|
+
object.run_callbacks(:laters) { object.send(method_name, *args, **kwargs) }
|
13
32
|
end
|
14
33
|
end
|
15
34
|
end
|
data/lib/laters/version.rb
CHANGED
data/lib/laters.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: laters
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kieran Klaassen
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2025-03-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -17,14 +17,34 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '5.0'
|
21
|
+
- - "<"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '9'
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '5.0'
|
31
|
+
- - "<"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '9'
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: thor
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.2.0
|
21
41
|
type: :runtime
|
22
42
|
prerelease: false
|
23
43
|
version_requirements: !ruby/object:Gem::Requirement
|
24
44
|
requirements:
|
25
45
|
- - ">="
|
26
46
|
- !ruby/object:Gem::Version
|
27
|
-
version:
|
47
|
+
version: 1.2.0
|
28
48
|
description: Deferrable empowers a class to run every single defined method wrapped
|
29
49
|
in an ActiveJob of any class that includes it
|
30
50
|
email:
|
@@ -34,6 +54,7 @@ extensions: []
|
|
34
54
|
extra_rdoc_files: []
|
35
55
|
files:
|
36
56
|
- CHANGELOG.md
|
57
|
+
- CLAUDE.md
|
37
58
|
- CODE_OF_CONDUCT.md
|
38
59
|
- LICENSE.txt
|
39
60
|
- README.md
|
@@ -57,14 +78,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
78
|
requirements:
|
58
79
|
- - ">="
|
59
80
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
81
|
+
version: 3.0.0
|
82
|
+
- - "<"
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '3.5'
|
61
85
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
86
|
requirements:
|
63
87
|
- - ">="
|
64
88
|
- !ruby/object:Gem::Version
|
65
89
|
version: '0'
|
66
90
|
requirements: []
|
67
|
-
rubygems_version: 3.
|
91
|
+
rubygems_version: 3.4.10
|
68
92
|
signing_key:
|
69
93
|
specification_version: 4
|
70
94
|
summary: Run any instance_method in ActiveRecord models via a job by adding `_later`
|