Cron jobs in Rails: A simple guide to ACTUALLY using the Whenever gem (now with tasks!)
Tags: rails, ruby, whenever, cron
Published: 2019-01-27 10:39:38

---
title: Cron jobs in Rails: A simple guide to ACTUALLY using the Whenever gem (now with tasks!)
published: true
description: 
tags: rails, ruby, whenever, cron
---

I had the chance to use `whenever` to schedule a task in Rails, and I'm writing this post for future reference. I know there are other ways to schedule regular tasks in Rails, but this is one - maybe the most - simple way to do it.
Note: Guide is for Linux or MacOS systems.


# What are cron jobs?
Cron is a job scheduler that lets you execute recurring tasks at fixed times (e.g. every minute, every hour, every day at 3pm).
Jobs are written in a file called the [crontab](https://www.adminschoice.com/crontab-quick-reference) (short for “cron table”), typically saved here: `/usr/bin/`

# Use `whenever` for cron jobs in Rails
[`Whenever`](https://github.com/javan/whenever) is a gem that helps you set up cron jobs. Instead of having to manually edit the crontab yourself, you can let `whenever` update the crontab for you by writing your jobs in Ruby code. You'll make your edits in `schedule.rb`

__Note:__ One thing worth mentioning is that the actual task itself (in my case, sending out batch messages periodically) should _not_ be written in the crontab, or in `schedule.rb`, the Rails file for writing in your crontab. The task itself should be written separately as a Rake task. You can then schedule that Rake task on a regular basis as a cron job.

## Steps
### 1. Install `whenever`
Include it in your app's `Gemfile`, and run `bundle` to install.

```ruby
gem 'whenever', require: false
```

### 2. Schedule your cron job in schedule.rb
`config/schedule.rb` is the file for specifying when to execute the job, and the name of the Rake task (again, the actual task should be written in a separate file).

Execute this from your Rails app root to create the `schedule.rb` file:

```
bundle exec wheneverize .
```

Now, write your job specifics in `schedule.rb`. For example, if you want to execute the Rake task `batch:send_messages` every minute:

```ruby
every 1.minute do
  rake 'batch:send_messages'
end
```

You can also do `every 2.hours` and `every 1.day` and so on.

### 3. Write the `whenever` task to your crontab
Let `whenever` write your job into the crontab.
```
bundle exec whenever --update-crontab
```

__Important__
`Whenever` takes into consideration your Rails app environment when writing to the crontab. If you're using the `development` environment, then run the command with the option below (default is `production`).

```
whenever --update-crontab --set environment='development'
```

For your reference, this is what your crontab will look like after running this command (`RAILS_ENV` is `development`):
```
# Begin Whenever generated tasks for: /Users/<USER>/<APPNAME>/config/schedule.rb at: 2019-01-14 18:15:41 +0900
* * * * * /bin/bash -l -c 'cd /Users/<USER>/<APPNAME> && RAILS_ENV=development bundle exec rake batch:send_messages --silent'

# End Whenever generated tasks for: /Users/<USER>/<APPNAME>/config/schedule.rb at: 2019-01-14 18:15:41 +0900

```

__Other commands__
- Display crontab: `crontab -l`
- Wipe crontab of your `whenever task`: `bundle exec whenever --clear-crontab`


### 4. Create the Rake task

Rake tasks follow a specific naming convention - namespace and task name. Namespaces are for grouping certain tasks together. For example, in the case below, if you had multiple batch tasks, you could put them all under `batch`.

Generate a file for your Rake task under `lib/tasks/batch.rake`. They follow the formula of:

`rails g task <NAMESPACE> <TASKNAME>`

So to generate our `send_messages` task in the `batch` namespace, we'll enter the following into terminal:

```
rails g task batch send_messages
```

Now write your task, which takes two parameters: `desc`, which is an arbitrary description of your task, and `task`, which is the code to be executed. 

For example:
```ruby
namespace :batch do
  desc 'Send out batch messages'
  task send_messages: :environment do
    # The code to actually send our messages would go here
  end
end
```

You can test your Rake task by executing it from the command line as below.

```
rails batch:send_messages
```


Thanks for reading!