Tuesday, February 19, 2008

Rake: Task Overwriting

Update at bottom

By default Rake Tasks append behavior every time they are defined. The following example shows that both definitions are executed.

require 'rubygems'
require 'rake'

task :the_task do
p "one"
end

task :the_task do
p "two"
end

Rake::Task[:the_task].invoke
# >> "one"
# >> "two"

I like this behavior, but sometimes you want to overwrite a task instead of appending to what's already there.

When you no longer want the existing behavior the overwrite method can come in handy.

require 'rubygems'
require 'rake'

class Rake::Task
def overwrite(&block)
@actions.clear
enhance(&block)
end
end

task :the_task do
p "one"
end

Rake::Task[:the_task].overwrite do
p "two"
end


Rake::Task[:the_task].invoke
# >> "two"

The overwrite method is good, but sometimes you want to redefine the task using one of the specialized Rake tasks. I recently wanted to redefine the test task, so I created the abandon method to remove the existing definition.

require 'rubygems'
require 'rake'
require 'rake/testtask'

class Rake::Task
def abandon
@actions.clear
end
end

task :the_task do
p "one"
end

Rake::Task[:the_task].abandon

Rake::TestTask.new(:the_task) do |t|
t.libs << "test"
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end

Rake::Task[:the_task].invoke
# >> Expectations ..................
# >> Finished in 0.00442 seconds
# >>
# >> Success: 18 fulfilled

Hopefully you wont need this type of thing very often, but it can be handy when you want to overwrite a task that has been previously by a framework you've included.

Update below...
Ola Bini pointed out that I'm not clearing the prerequisites. Clearing the prerequisites is something you can do without any modifications to rake.

Rake::Task[:task_name].prerequisites.clear

Also, if you want prerequisites cleared as part of overwrite or abandon, you can easily add it to both tasks.

class Rake::Task
def overwrite(&block)
@actions.clear
prerequisites.clear
enhance(&block)
end
def abandon
prerequisites.clear
@actions.clear
end
end
Post a Comment