I was playing around with rake the other day in an attempt to make Spree compatible with Rails 2.1 when I discovered an interesting new feature.  I began by experimenting with overriding the 'db:migrate' task that ships with Rails.  I took the original contents of the task and pasted them into my new rake file.  I then modified them by adding other steps.

Everything was working fine until I tried to modify ':abort_if_pending_migrations.' I kept getting only the listing of regular migrations that were to be run (instead of my the additional migrations that I was adding in my overloaded rake task.)  After struggling with this for a little while I realized something.  Rake isn't overriding these tasks, its calling both of them!

I verified this with the following simple experiment.

foo.rake


task :bar => :foo do
  puts "bar"
end

task :foo do
  puts "foo"
end

$ rake foo
foo
bar

foo_monkey.rake


task :foo do
  puts "monkey: foo"
end

task :bar do
  puts "monkey: bar"
end

$ rake foo
foo
monkey: foo
bar
monkey: bar