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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2aee3b69a94b76dc761316d2e253ffff6088ada2a7eb497ecf4961a30282c590
4
- data.tar.gz: 0c8ae9f7a7a0c68de7a8c4ffa01f74139e4dca5dc965d547188eccb26e00dd2d
3
+ metadata.gz: 85e450085da66e2a32ab240a767416ee4f4c7cb04d891a4e6d4b1ec8c2febe15
4
+ data.tar.gz: 7ffc6eae552ccab18d82b24e736e4c1969fcb6aa51425c82489cea16e5cd0f79
5
5
  SHA512:
6
- metadata.gz: 7537a040568057b45520ab42e17a6e78634c4b01328d1c62ed9a70a1850eee8ba5dc7944c7a82614b6d9a985be855f584f37196dbd49a17dba89ca611c259b0a
7
- data.tar.gz: 609d062a4e36d0734a488d7c7e57112d20fc1739643889a8c80af5dbe4183e94c0a2b68aac3d2d5c81bb1e954181467341eb75f2580418fb0ae55c689696fec8
6
+ metadata.gz: 4930a10d29d4704bc1848100d84d035f38d560f8c9ef5985d7e3d21d9c77c3541750f845762ec311be29cafa17e294ede912c230802fb4dc5ccd3428c97913fb
7
+ data.tar.gz: 4cf150e51867955a1941a42af2df24444962d934f7fe551b8fb4380d12bd12acd3466b0c6ebf0afc51635ed3ead2bf7e238693d46c8b025225759fb8abc724ae
data/CHANGELOG.md CHANGED
@@ -1,4 +1,29 @@
1
- # Master
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
+ [![Gem Version](https://badge.fury.io/rb/laters.svg)](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 👋, means See you later in
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
- [![Actions Status](https://github.com/kieranklaassen/laters/workflows/build/badge.svg)](https://github.com/kieranklaassen/laters/actions)
7
- [![Gem Version](https://badge.fury.io/rb/laters.svg)](https://badge.fury.io/rb/laters)
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 :refresh_cache_later
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 refresh_cache!
39
- # Expensive calculation
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
- If you need callbacks, they are provided as standart model callbacks:
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
@@ -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
- def method_missing(method, *args, &block)
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(queue: self.class.job_queue || :default)
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 InstanceMethodJob < ActiveJob::Base
5
- def perform(object, method_name, *args)
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
@@ -1,3 +1,3 @@
1
1
  module Laters
2
- VERSION = '0.1.2'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
data/lib/laters.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'laters/version'
2
+
3
+ require 'active_support'
2
4
  require 'active_model'
3
5
  require 'active_job'
4
6
  require 'laters/concern'
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.1.2
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: 2020-08-26 00:00:00.000000000 Z
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: '4.2'
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: '4.2'
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: 2.3.0
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.1.2
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`