Rake Tasks 101
I’ve been working with Rake quite a bit on my current project so I thought I’d share some beginner tips.
Before I go into Rake, what is it? Rake is a Ruby-based build program. Ruby on Rails uses Rake quite a bit in it’s process. If you’ve worked on a Rails project you’ll used one, some or all of the following: rake db:create, rake gems:unpack, rake db:migrate, and rake test. Now that’s not all of Rail’s Rake tasks, just some common ones.
You’re here to make your own Rake tasks so lets get started!
Make Your Task
Rake files can live within plugins or in your Rails.root/lib/tasks
directory. In this post I’ll be referencing the latter. Let’s create our
new rake file: Rails.root/lib/tasks/manners.rake
Next we can declare our Rake task in the manners.rake file:
namespace :manners do
desc 'the description of what my rake task will do'
task :greet do
puts 'Hello from Rake'
end
end
After thats done we should be able to execute our new task at the
command-line with rake manners:greet
.
Task Variables
Let’s make the Rake task reusable. To do this we’ll pass in some variables. Rewrite the task block of the manners.rake file like this:
task :greet, :name do |cmd, args|
puts "command: #{cmd}"
puts "args: #{args.inspect}"
end
The output you receive from running the task again should look like this:
command: manners:greet
args: {}
Now run the task again, but define the variable by calling it like this,
rake manners:greet[Dane]
. That should yield:
command: manners:greet
args: {:name => "Dane"}
This is where Rake tasks get interesting. Rake always passes in the
command run into the task block as the first variable, thats why we see
“command: manners:greet.” The second variable defines the hash that
will contain all the variables passed into the the Rake task. The args
hash index is any symbol that follows the task name symbol. We set
:greet
as the task name so :name becomes an available index in the args
hash.
Lets rework the :greet
task a little bit by defining our variables as
:first_name
and :last_name
.
task :greet, :first_name, :last_name do |cmd, args|
puts "Good day #{args[:first_name]} #{args[:last_name]}"
end
Run the Rake task and define both variables, rake manners:greet[Dane,Harrigan]
.
Spaces are not allowed when passing variables into a Rake task when
calling it at the command-line. This is why its written as
[Dane,Harrigan]
and not [Dane, Harrigan]
. Quotes can be used if
spaces are necessary to a variable for example, rake manners:greet['Mr. Dane',Harrigan]
.
Rake Dependencies
We’ve built a Rake task so now lets make another and have it depend on
manners:greet
. Add a manners:question
task that asks, “How are you?”
Start by just making a Rake task like we did with manners:greet
. To
make the :question
task dependent on :greet
define the task as task :question => 'manners:greet'
. Our manners.rake
file should look like
this:
namespace :manners do
desc 'Greet the Rake user'
task :greet, :first_name, :last_name do |cmd, args|
puts "Good day #{args[:first_name]} #{args[:last_name]}"
end
desc 'Ask a question'
task :question => 'manners:greet' do
puts 'How are you doing?'
end
end
If we run rake manners:question
you’ll see that it greets us with,
“Good day,” and, “How are you doing?” but we can’t set variables in a
task dependency when its declared this way. Defining the dependency this
way doesn’t work either, task :question => 'manners:greet[Dane,Harrigan]'
. Let’s remove the ‘manners:greet’
dependency and call invoke
on it instead.
task :question do
Rake::Tasks['manners:greet'].invoke('Dane','Harrigan')
puts 'How are you doing?'
end
Now when we run the task you’ll see a greeting to Dane and the question.
Tasks Run Once
When calling a task with invoke
or execute
Rake keeps track of
whether or not it has already run. If the task has run already it wont
run a second time. If we did the following you’ll only see one greeting.
task :question do
Rake::Task['manners:greet'].invoke('Dane','Harrigan')
Rake::Task['manners:greet'].invoke('John','Smith')
puts 'How are you doing?'
end
You won’t see the greeting to John Smith. Well that’s rude, but we can
fix this easily. If you want to call the task multiple times you’ll need
to reenable
the task each time before calling it. You can reenable
a
task anywhere, but I’ve found it makes the most sense to call reenable
at the end of the task block of the one being reenabled. In our example
we’ll call reenable
inside of task :greet
.
task :greet, :first_name, :last_name do |cmd, args|
puts "Good day #{args[:first_name]} #{args[:last_name]}"
Rake::Task['manners:greet'].reenable
end
Now if we call rake manners:question
we’ll see both greetings.
Perfect!
And We’re Done
Rake is a very nice piece of software and I encourage others to read up on it. I hope this post gave you enough understanding to start writing your own tasks. Also, please do comment if there are questions or other areas of Rake you’d like to know about. A Rake Tasks 102 post perhaps?
Rake Tasks 102 is up! If you liked Rake Tasks 101, I think you’ll enjoy 102 just as much.