
- Ruby on Rails - Home
- Ruby on Rails - Introduction
- Ruby on Rails - Installation
- Ruby on Rails - IDEs
- Ruby on Rails - Hello World
- Ruby on Rails - Framework
- Ruby on Rails - Directory Structure
- Ruby on Rails - Rails Console
- Ruby on Rails - Bundler
- Ruby on Rails - Examples
- Ruby on Rails - Database Setup
- Ruby on Rails - Active Records
- Ruby on Rails - Validation
- Active Record Associations
- Active Record Query
- Ruby on Rails - Migrations
- Ruby on Rails - Active Model
- Ruby on Rails - Controllers
- Cookies and Session
- Ruby on Rails - Authentication
- Ruby on Rails - Routes
- Ruby on Rails - Views
- Ruby on Rails - Rendering
- Ruby on Rails - Layouts
- Ruby on Rails - Scaffolding
- Ruby on Rails - Forms
- Ruby on Rails - Active Jobs
- Ruby on Rails - Action Text
- Ruby on Rails - Active Storage
- Ruby on Rails - JavaScript
- Ruby on Rails - Propshaft
- Ruby on Rails - ImportMap
- Ruby on Rails - AJAX
- Ruby on Rails - WebSockets
- Ruby on Rails - Action Cable
- Ruby on Rails - File Uploading
- Ruby on Rails - Send Emails
- Ruby on Rails - Rack
- Ruby on Rails - Error Handling
- Ruby on Rails - Deployment
- Ruby on Rails Resources
- Ruby on Rails - References Guide
- Ruby on Rails - Quick Guide
- Ruby on Rails - Resources
- Ruby on Rails - Discussion
- Ruby Tutorial
- Ruby Tutorial
Ruby on Rails - Active Job
The Active Job framework in Rails is extremely helpful for declaring background jobs and executing them asynchronously.
Applications that involve background tasks such as sending emails, pushing notifications, background processing of CSV files and backing up the databases, integration with external apps through APIs, handling file uploads, etc., can be scheduled with Active Job framework.
Emails with Active Job
As explained in the previous chapter (Ruby on Rails – Sending Emails), there is a welcome_email() method in the UserMailer class.
class UserMailer < ApplicationMailer default from: " GMAIL_USERNAME" def welcome_email(user) @user = user mail(to: @user.email, subject: "Welcome to My Awesome Site!") end end
Next, you need to create an Active Job with the following command:
rails generate job send_emails
This creates a custom job (SendEmailsJob) to handle the email-sending process asynchronously.
Active Job provides a default perform() method which you need to override to call the welcome_email() method from the UserMailer class.
class SendEmailsJob < ApplicationJob queue_as :default def perform(user) UserMailer.welcome_email(user).deliver end end
You now need to install a queuing service to handle the background jobs. We have a variety of background queuing libraries such as delayed jobs, sidekiq, rescue, and so on.
We will be using Sidekiq for the active job. For that, we must add a gem of sidekiq into Gemfile:
gem 'sidekiq' bundle install
However, you need to let Rails know that this gem is to be used for background processing. So, edit your application.rb to set the active_job.queue_adapter.
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
Enqueuing the job
After configuring queueing backend, you must add your job to the queue. Enqueue a job for execution when the queuing system is available. Along with it, the queue will change whenever the time changes. You may set times for when a task needs to be completed 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 |
For example,
SendEmailsJob.set(wait: 1.week).perform_later(user)
This statement schedules sending the email 1 week from now. Or,
SendEmailsJob.set(wait_until: Date.tomorrow.noon).perform_later(user)
Will start the job tomorrow at noon.
Recent versions of Ruby on Rails do not require you to generate a custom job when you're just using ActionMailer with deliver_later. To enable Active Job in your Rails application for sending emails asynchronously (such as when a User is created), you just need to queue the email delivery job instead of sending it directly.
Edit your UserController and modify the create action as below:
def create @user = User.new(user_params) if @user.save # UserMailer.welcome_email(@user).deliver_now # Send email after user creation UserMailer.welcome_email(@user).deliver_later # Send email later redirect_to @user, notice: "User was successfully created. A welcome email has been sent." else render :new, status: :unprocessable_entity end end
You can specify the wait parameter to deliver_later() method such as −
UserMailer.welcome_email(user).deliver_later(wait: 10.minutes)
Or,
UserMailer.welcome_email(user).deliver_later(wait_until: Time.tomorrow.noon)
Callbacks
The Active Job framework has certain hooks so that a defined logic can be triggered at various points during a job’s life cycle. These are the available callbacks for active jobs:
Callback | Description |
---|---|
before_enqueue | Defines a callback that will get called right before the job is enqueued. |
around_enqueue | Defines a callback that will get called around the enqueuing of the job. |
after_enqueue | Defines a callback that will get called right after the job is enqueued. |
before_perform | Defines a callback that will get called right before the jobâs perform method is executed. |
around_perform | Defines a callback that will get called around the jobâs perform method. |
after_perform | Defines a callback that will get called right after the jobâs perform method has finished. |
Retrying or Discarding Failed Jobs
It's possible to retry or discard a failed job by using retry_on or discard_on, respectively. 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.