In my current project we have a lot of ActiveJobs most of them only need to run in production, that’s why I wrote this Rails concern. This concern allows you to skip certain jobs in development.
Below is an example .yml file we have to determine what jobs run in development.
module Cancelable
extend ActiveSupport::Concern
included do
around_perform do |job, perform|
perform.call unless Cancelable.allowed?
if Cancelable.allowed?
file_name = "jobs/#{job.class.name.underscore}.rb"
constant_name = Cancelable.setting_name(job.class)
setting = Setting.find_or_create_by(name: constant_name) do |new_setting|
new_setting.value = Cancelable.default_setting_for(constant_name, default: true)
new_setting.description = "Automatically created in #{file_name}"
end
if setting.value
perform.call
else
Rails.logger.info "♦ Job #{job.class} is disabled (#{Rails.application.routes.url_helpers.admin_setting_url(setting)})"
end
end
end
end
def self.allowed?
Rails.env.development?
end
def self.setting_name(clazz)
clazz.name
end
def self.default_setting_for(constant_name, default:)
value = YAML.load_file("config/default_jobs.yml").dig(constant_name)
value.nil? ? default : value
end
end
This is how to use it:
class MyJob < ApplicationJob
include Cancelable
def perform
# do something
end
end
The RSpec test:
class CancelableTestJob < ApplicationJob
def perform = CheckIn.do!("Test", reporting_interval: 5.minutes, grace_period: 3.minutes)
end
describe Cancelable do
subject(:test_job) { CancelableTestJob.new }
before { allow(CheckIn).to receive(:do!) }
context "when cancelable is not active" do
before { allow(Cancelable).to receive(:allowed?).and_return(false) }
it "can not be canceled with a default config" do
allow(Cancelable).to receive(:default_setting_for).with("CancelableTestJob", default: anything).and_return(false)
test_job.perform_now
expect(CheckIn).to have_received(:do!)
expect(Setting).to have(0).settings
end
end
context "when cancelable is active" do
before { allow(Cancelable).to receive(:allowed?).and_return(true) }
it "is executed and creates a new setting with a true value" do
test_job.perform_now
expect(CheckIn).to have_received(:do!)
expect(Setting).to have(1).setting
expect(Setting.first.name).to eq "CancelableTestJob"
expect(Setting.first.value).to eq true
end
it "can be canceled with a default config" do
allow(Cancelable).to receive(:default_setting_for).with("CancelableTestJob", default: anything).and_return(false)
test_job.perform_now
expect(CheckIn).not_to have_received(:do!)
expect(Setting).to have(1).setting
expect(Setting.first.name).to eq "CancelableTestJob"
expect(Setting.first.value).to eq false
end
it "can be allowed with a default config" do
allow(Cancelable).to receive(:default_setting_for).with("CancelableTestJob", default: anything).and_return(true)
test_job.perform_now
expect(CheckIn).to have_received(:do!)
expect(Setting).to have(1).setting
expect(Setting.first.name).to eq "CancelableTestJob"
expect(Setting.first.value).to eq true
end
describe ".setting_name" do
it "returns the name of a setting" do
expect(Cancelable.setting_name(Tesla::DetectPluggedInJob)).to eq "Tesla::DetectPluggedInJob"
end
end
end
end
This is our config:
DataSource::GridImbalanceJob: false
DataSource::GridFrequencyJob: false
DataSource::SolarDataJob: false
DataSource::SolarLogJob: false
ElaadSubmitMeasurementsJob: false
ImportEfluxSessionsJob: false
Like this post? Follow me at @jankeesvw on Twitter