Skip to content

Instantly share code, notes, and snippets.

@6temes
Created February 8, 2024 03:52
Show Gist options
  • Save 6temes/c2ac70ecf68529b1559c6cb973f8392d to your computer and use it in GitHub Desktop.
Save 6temes/c2ac70ecf68529b1559c6cb973f8392d to your computer and use it in GitHub Desktop.
Pass Current attributes to Good Job
#
# Injects the Current attributes into the job arguments automatically when enqueuing
# and sets the Current attributes from the job arguments when performing.
# For testing, you can pass the current attributes as the last argument to `perform_later`:
#
# MyJob.perform_later(arg1, arg2, _current_attributes: { person: person, trust: trust })
#
# This will set the Current attributes to the given values when performing the job.
#
# If you want to set the Current attributes when enqueuing the job, include this module in your job class:
#
# class MyJob < ApplicationJob
# include IncludesCurrentAttributes
#
# def perform(arg1, arg2)
# # ...
# end
# end
#
module IncludesCurrentAttributes
extend ActiveSupport::Concern
included do
extract_current_attributes_argument = lambda do |job|
current_attributes = if job.arguments.last.is_a? Hash
job.arguments.last.delete :_current_attributes
end
current_attributes || {}
end
around_enqueue do |job, block|
current_attributes = extract_current_attributes_argument.(job)
if job.arguments.last.is_a? Hash
job.arguments.last[:_current_attributes] = Current.attributes.merge(current_attributes)
else
job.arguments << { _current_attributes: Current.attributes }
end
block.call
end
around_perform do |job, block|
current_attributes = extract_current_attributes_argument.(job)
Current.attributes = current_attributes if current_attributes.present?
block.call
ensure
Current.reset
end
end
end
require 'rails_helper'
class DummyJob < ApplicationJob
include IncludesCurrentAttributes
def perform(*_args)
$test_current_attributes_for_IncludesCurrentAttributes = # rubocop:disable Style/GlobalVars
Current.attributes
end
end
RSpec.describe IncludesCurrentAttributes do
include ActiveJob::TestHelper
before do
ActiveJob::Base.queue_adapter = :test
Current.agency = 'Test Agency'
Current.trust = 'Test Trust'
Current.person = 'Test Person'
end
after do
clear_enqueued_jobs
clear_performed_jobs
$test_current_attributes_for_IncludesCurrentAttributes = nil # rubocop:disable Style/GlobalVars
end
it 'injects Current attributes into job arguments when enqueuing and sets them when performing',
:aggregate_failures do
DummyJob.perform_later(
'arg1',
'arg2',
_current_attributes: { person: 'Overwritten Test Person' },
)
args = enqueued_jobs.last[:args]
expect(args.last).to be_a Hash
expect(args.last.keys).to include '_current_attributes'
current_attributes = args.last['_current_attributes']
expect(current_attributes).to include(
'agency' => 'Test Agency',
'trust' => 'Test Trust',
'person' => 'Overwritten Test Person',
)
perform_enqueued_jobs
# There is no way to access the job instance directly, so we use a global variable.
# We made sure that the global variable is sufficiently unique to avoid conflicts.
# This could blow up if we ran the tests in parallel and had several tests using,
# the same global variable, but we don't.
expect($test_current_attributes_for_IncludesCurrentAttributes).to include( # rubocop:disable Style/GlobalVars
agency: 'Test Agency',
trust: 'Test Trust',
person: 'Overwritten Test Person',
)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment