Friday, February 4, 2011

How to find the name of the current Rake task


A few weeks ago I needed a Rake task to answer a simple question for me:
“What’s my name?”
I honestly can’t quite remember why exactly the task needed to know it’s own name, but at the time it seemed important and I spent a couple hours digging about before I found out that Rake tasks are shy by nature. Or at least when implemented the way almost every tutorial tells you to implement them:
namespace :life do

desc "The answer to life, the universe, and everything"
task :answer do
puts "The answer to life, the universe, and everything is 42."
end

end
But how do I know what the name of the current task is? Well, after making a couple of random attempts (like “puts task.name”) and digging around in the very sparsedocumentation on the Rake homepage, I stumbled across a bit of documentation that talked about “Tasks with Actions”:
Actions are defined by passing a block to the task method. Any Ruby code can be placed in the block. The block may reference the task object via the block parameter.
task :name => [:prereq1, :prereq2] do |t|
# actions (may reference t)
end
Ah ha! “The block may reference the task object via the block parameter.” That’s exactly what I was looking for. Adding the block parameter allows us to reference the task object itself. And the task object itself has a good bit of useful meta information:
namespace :life do

desc "The answer to life, the universe, and everything"
task :answer do |t|
puts t.name
puts t.comment
puts t.scope
end

end
The task now returns the following:
life:answer
The answer to life, the universe, and everything
life
The first line of output is nifty, and answers the “What’s my name?” question with the fully scoped name of the task. Given that much it’s probably not hard to return the task name in even the most deeply namespaced Rakefile. The second line is the “comment” — actually the description of the task. And the third line gets us the scope (namespaces). There are more methods available, but check teh googles for “Rake::Task api”.
So with this meta information we can do something useful like:
namespace :life do

desc "The answer to life, the universe, and everything"
task :answer do |t|
puts "#{t.comment} is 42."
end

end

1 comment: