ActiveJob In Ruby On Rails

Tejal Panjwani
5 min readApr 18, 2023

--

Rails now come with built-in support for running jobs in the background. ActiveJob was first made available in Rails 4.2.

A framework called ActiveJob allows you to set up jobs and have them execute on various asynchronous queuing backends. We can define jobs for creating, queuing, and executing jobs by using an active job.

Use of an active job

The active job provides a layer of abstraction above all the different background job frameworks (Delay job, Sidekiq, Resque and so ).

As an outcome, you can switch background job frameworks without thinking too much about what background process you’ll implement.

As a result, selecting your queue backend becomes more of a technical decision. And you won’t have to rewrite your jobs to switch between them.

In simple terms, ActiveJob stands for the API interface for the job queue. This will make it easier for you to switch from one background job framework to another.

ActiveJob Example

In order, ActiveJob does not automatically do background tasks. Still missing is one of the background job frameworks. Let’s say you’ve decided to use background job frameworks such as Sidekiq, Delay job, and so on.

What does mean by background job?

If we run any task or job on your main web application, it makes your application slow. Therefore, we perform certain jobs outside the typical request/response cycle.

  • Sending an email.
  • Processing & compression of video
  • Upload and download CSV files that contain an enormous amount of data.
  • Putting an image into an S3 bucket
  • Create an image from a PDF

Anything that can be divided up into smaller tasks and executed in parallel.

Let’s explore an example of an active job. Every user who registers for the application receives a welcome email from the application.

Step 1: Create UserMailer

Using mailer classes and views, ActionMailer enables you to send emails from your application. Mailer classes are inherited from ActionMailer::Base and exist under the app/mailers directory.

Let’s generate a user mailer first for sending emails.

rails g mailer user

Following the execution of the above command, an app/mailer/user_mailer.rb generated under the app/mailers directory. We can generate views for user_mailer under the app/views/user_mailer directory and additionally generate test/mailers/user_mailer_test.rb file for the purpose of testing (write a test case).

The result of the rails g mailer user command

Let’s create an action welcome_email for sending a welcome email to the user.

# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
def welcome_email(user)
@user = user
mail to: @user.email, subject: "Welcome Email!!"
end
end

Let’s add template for welcome email create welcome_email.html.erb under app/views/user_mailer/

<!-- app/views/user_mailer/welcome_email.html.erb -->
<h1>
Welcome Email to <%= user.first_name %>
</h1>

In order to call the user_mailer, we should first establish an active job.

Step 2: Create an ActiveJob

rails g job job-name

I’ll use the job name send_emails in this case.

rails g job send_emails

Following the execution of the above command, an app/jobs/send_emails_job.rb generated within the app/jobs folder and additionally generated test/jobs/send_emails_job_test.rb file or the purpose of testing. (write a test case).

The result of the rails g job send_emails command

Without utilizing the command line, it is also possible to create a job manually. Generate a file in the app/jobs directory and inherit your class from ApplicationJob, and ApplicationJob inherit from ActiveJob::Base

Here, perform is a default method provided by ActiveJob. Your job will be as follows:

# app/jobs/send_emails_job.rb
class SendEmailsJob < ApplicationJob
queue_as :default

def perform(user)
# Do something later
end
end

Step 3: Send a “welcome email” to each new user after they sign up

In this section, when a user is created, send them a welcome email. Let’s look into it.

class User < ApplicationRecord
after_create :send_welcome_email

private
def send_welcome_email
SendEmailsJob.perform_now(self)
end
end

Using perform_now we can enqueue a job, which actually calls perform on the job.

The perform_now and perform_later is a class method that comes from the ActiveJob::Enqueuing concern.

Step 4: Call Mailer from ActiveJob

Call the mailer from jobs. At this point, we call UserMailer’s welcome_email action from send_email_job.rb

# app/jobs/send_emails_job.rb
class SendEmailsJob < ApplicationJob
queue_as :default

def perform(user)
UserMailer.welcome_email(user).deliver
end
end

Step 5: Setup Background Job

The majority of queuing libraries require that you start a library-specific queuing service since jobs run simultaneously with your Rails application.

We have a variety of background jobs such as delayed jobs, sidekiq, rescue, and so on.

Let’s start integrating Sidekiq for the active job. For that, we must add a gem of sidekiq into Gemfile:

gem 'sidekiq'

Run using the below integrate sidekiq into an application:

bundle install

We must inform the rails application that will be using sidekiq with our background processor. In order to do that, we configured queuing backed using config.active_job.queue_adapter into config/application.rb file

# config/application.rb
module MyApplication
class Application < Rails::Application
# make sure the adapter's gem has been included in your Gemfile.
config.active_job.queue_adapter = :sidekiq
end
end

You can combine ActiveJob with any background job in this manner.
Let’s now explore ActiveJob in more depth.

Enqueue Job:

You must add your job to the queue for execution after successfully configuring queueing backend.

There are numerous ways to queue a job. Basically, a job is placed into a queue for execution when it is enqueued.

Enqueue a job for execution when the queuing system is available. Along with it, the queue will change whenever the time changes.

Additionally, we may set times for when a task needs to be completed, for example, you may schedule it to be executed after a month or to be executed as soon as possible.

Considering that SendEmailsJob is the name of our job. The multiple techniques listed below can be used to achieve enqueuing options.

  • wait: Enqueues the job with the specified delay
  • wait_until: Enqueues the job at the time specified
  • queue: Enqueues the job on the specified queue
  • priority: Enqueues the job with the specified priority

let’s consider an example below:

# Schedule a job to begin 1 week from now.
SendEmailsJob.set(wait: 1.week).perform_later(user)

# Schedule a job to begin tomorrow at noon.
SendEmailsJob.set(wait_until: Date.tomorrow.noon).perform_later(user)

Callbacks

Hooks are provided by Active Job so that logic can be triggered at various points during a job’s life cycle. The callbacks can be implemented via standard methods, just like other callbacks in Rails, and then register as callbacks via a class method.

Let’s see the below example for ActiveJob callback.

class SendEmailsJob < ApplicationJob
queue_as :default

before_perform { |job| puts job.arguments }
around_perform :around_cleanup

after_perform do |job|
record = job.arguments.first
# Do something with the record
end

def perform
# Do something later
end

private
def around_cleanup
# Do something before perform
yield
# Do something after perform
end
end

Available callbacks for active jobs are as below:

  • before_enqueue
  • around_enqueue
  • after_enqueue
  • before_perform
  • around_perform
  • after_perform

Retry On:

If the configuration doesn’t specify, a failed job will not be retried. Using retry_on or discard_on, respectively, you can attempt again after a failed job. And default retry_on is to 3 seconds and 5 attempts.

Please like and share if you like reading this. And please don’t hesitate to contact me if you have any questions. I’m grateful you took the time to read this tutorial🙌.

--

--