Rails 7 adds range serializer for ActiveJob


When using Rails, we often need to run tasks in the background without affecting website performance. Rails 4.2 introduced the ActiveJob framework to standardize scheduling background jobs.

A simple example where the ActiveJob use-case fits correctly is sending an email verification when a user signs up as shown below.

class EmailVerificationJob < ActiveJob::Base

  def perform(user_id:, email_verification_code:)
    # send verification code to user email
  end
end

In the above example, we have passed user_id and email_verification_code as arguments to the perform method. ActiveJob performs serialization and deserialization on these arguments. The below argument types are supported (before Rails 7) by default:

Basic types (NilClass, String, Integer, Float, BigDecimal, TrueClass, FalseClass)
Symbol
Date
Time
DateTime
ActiveSupport::TimeWithZone
ActiveSupport::Duration
Hash (Keys should be of String or Symbol type)
ActiveSupport::HashWithIndifferentAccess
Array
Module
Class

Before

As seen in the above list Range as an argument was not supported before Rails 7.

Let’s take an example where for a given date range we need to pass log report to admins. If we try to pass the date range as an argument, it raises an error as shown below:

class AdminReportJob < ActiveJob::Base
  queue_as :default

  def perform(date_range:)
    # code to fetch report for the passed date range
  end
end

start_date = Date.today - 3.days
end_date = Date.today

AdminReportJob.perform_later(date_range: start_date..end_date)
Failed enqueuing AdminReportJob to Sidekiq(default): ActiveJob::SerializationError (Unsupported argument type: Range)

In Rails 6 or above, we can resolve the above issue by adding a custom serializer for the Range argument type. To know more about custom serializers, please refer to our previous blog.

After

With the changes in Rails 7, we can now pass range as an argument type and avoid adding custom serializers.

The above AdminReportJob will work without raising any error.

class AdminReportJob < ActiveJob::Base
  queue_as :default

  def perform(date_range:)
    # code to fetch report for the passed date range
  end
end

start_date = Date.today - 3.days
end_date = Date.today

AdminReportJob.perform_later(date_range: start_date..end_date)
=> Enqueued AdminReportJob (Job ID: d5688e0c-e826-4587-9413-1309a2332f0e) to Async(default) with arguments: Thu, 20 May 2021..Sun, 23 May 2021