Skip to Content
Course content

31: Introduction to Rake Tasks

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I remember early in my career, I wrote a quick Rake task to prune old logs from a staging database. I was in a rush, and I wrote something like this in my Rakefile:

# Rakefile
desc "Clean up old logs"
UserLog.where('created_at < ?', 30.days.ago).destroy_all
task :cleanup_logs do
  puts "Logs cleaned up!"
end

I thought I was being clever by putting the "heavy lifting" above the task definition. But then something terrifying happened. Every single time I ran rake -T just to see a list of available tasks, my database started deleting records. I didn't even have to execute the cleanup task for the cleanup to happen.

The Danger of Top-Level Execution

The mistake I made here is a fundamental misunderstanding of how Rake works. When you run any rake command, Rake doesn't just look for the specific task you requested; it first loads the entire Rakefile to build a map of all available tasks and their dependencies.

Because I placed the destroy_all call outside of the task :cleanup_logs do ... end block, that code became part of the file's top-level execution. In Ruby, anything not wrapped in a method or a block runs immediately when the file is required or loaded. So, every time Rake "read" my file, it executed the deletion logic.

Encapsulating Logic in a Task Block

To fix this, the logic must be moved inside the block associated with the task. The block is a closure; it's stored by Rake and only executed when that specific task is explicitly invoked.

# The corrected Rakefile
desc "Clean up old logs"
task :cleanup_logs do
  UserLog.where('created_at < ?', 30.days.ago).destroy_all
  puts "Logs cleaned up!"
end

Now, when you run rake -T, Rake sees the desc and the task definition, notes that :cleanup_logs exists, and moves on without actually running the code inside the block. The database stays safe until you explicitly run rake cleanup_logs.

Organizing Tasks with Namespaces

As your project grows, you'll find that a flat list of tasks becomes a mess. If you have a cleanup_logs task and a cleanup_users task, your rake -T output starts to look cluttered. I always recommend using namespaces to group related functionality. It's essentially like creating a folder for your tasks.

namespace :db do
  desc "Clean up old logs"
  task :cleanup_logs do
    # logic here
  end

  desc "Reset temporary tables"
  task :reset_temp do
    # logic here
  end
end

Now, to run these, you use a colon: rake db:cleanup_logs. It keeps your global namespace clean and prevents naming collisions.

Handling Task Dependencies

Sometimes, one task can't run unless another one has finished first. For example, you shouldn't try to clean up logs if the database connection hasn't been established yet. Rake handles this with a simple hash-like syntax in the task definition.

task :ensure_db_connected do
  puts "Connecting to DB..."
  # Connection logic here
end

namespace :db do
  desc "Clean up old logs"
  task :cleanup_logs => :ensure_db_connected do
    puts "Cleaning logs now that we are connected!"
  end
end

In the example above, :cleanup_logs => :ensure_db_connected tells Rake: "Before you run the cleanup logic, go find the task called :ensure_db_connected and run it first." This is incredibly powerful for building complex build pipelines or data migration sequences without manually calling one task from another.




📋 Practical Task

The CSV Data Import Pipeline

You are building a system to import product data from a CSV file. You need to create a Rakefile that implements a two-step pipeline to ensure data integrity.

  • Create a task named :validate_csv. For this exercise, it should simply puts "Validating CSV format...".
  • Create a namespace called :import.
  • Inside that namespace, create a task called :products.
  • The import:products task must depend on the validate_csv task.
  • The logic inside import:products should puts "Importing products into the database...".
  • Ensure both tasks have a desc (description) so they show up when running rake -T.

Verification: When you run rake import:products, your output should show the validation message first, followed by the import message.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.