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.