How to Access Rails Models in a Rake Task

How to Access Rails Models in a Rake Task

This article shows how you can access your application models inside rake tasks by adding the `environment` task as a dependency. We'll also go one level deeper and learn exactly how it works behind the scenes.

2 min read

If you’ve been working with Rails for a while, you must have come across Rake. In fact, the very first post on this blog was a brief introduction to Rake. Written by the late Jim Weirich (my Ruby hero), Rake is to Ruby what make is to C. It’s very easy to create custom Rake tasks to simplify your development workflows. Rails even provides a generator (rails g task) to create them for you.

However, one question that many new Rails developers have when learning Rails is how to access the Rails models in a Rake task, which is very useful for running some application logic or performing database queries via the command line. This article shows how to do it.

TL;DR

Add the :environment task as the dependency for your custom task. It's that simple.

task count_users: [:environment] do
  puts User.count
end

That's it. Now you can access any models in the task.

Long Answer

Here’s a simple Rake task that tries to use an ActiveRecord model named User.

# lib/tasks/count.rake

desc "count the number of users in the system"
task :count_users do
  puts User.count
end

If I try to run this Rake task as it is, Rails throws a NameError, as it doesn’t know what User refers to. It has no idea about the context of our Rails application. No constants have been loaded.

$ bin/rails count_users

rails aborted!
NameError: uninitialized constant User

  puts User.count
       ^^^^^^^^^^^^^^^

To make the ActiveRecord models available in the Rake tasks, we must tell Rails to load the environment before running the task. This is similar to what happens when you launch the Rails console.

Loading the Rails environment gives you access to the ActiveRecord models, database, and much more.

Rails provides an :environment task to load the environment. In Rake terminology, your task is dependent on the :environment task, as it must be performed before your task.

# lib/tasks/count.rake

desc "count the number of users in the system"
task count_users: [:environment] do
  puts User.count
end

Now you can access the User model in the rake task without any errors.

Digging Deeper

The :environment task is defined in the railties/lib/rails/application.rb file. All it does is load the config/environment.rb file in your application, which is what Rails does when you launch your application.

Here's a simplified version of the underlying code.

task :environment do
  require_environment!
end

def require_environment! # :nodoc:
  environment = paths["config/environment"].existent.first
  require environment if environment
end

The environment.rb file will first require the application.rb file and then call the initialize method on your application. This is exactly how your Rails application boots up when you launch it.  

# config/environment.rb

# Load the Rails application.
require_relative "application"

# Initialize the Rails application.
Rails.application.initialize!

And that's how you can access your Rails models inside a Rake task.


I hope you found this article useful and that you learned something new.

If you have any questions or feedback, didn't understand something, or found a mistake, please leave a comment below or send me an email. I look forward to hearing from you.

Please subscribe to my blog if you'd like to receive future articles directly in your email. If you're already a subscriber, thank you.