Is it a good idea to replace some or all of your [N]Ant build with Rake? 
I finally decided to find it out, by actually doing it (*)

The story begins with a fairly normal, run of the mill, Nant build for a 
.NET project, building a fairly normal, run of the mill, enterprise 
application. Broadly, the build consists of three parts: database, 
compile/test and packaging for deployment. It took me several evenings 
(~20 hours total) to reimplement it with Rake and a couple of weeks to 
get pretty much everybody in the project to switch over to it.

My conclusion is "Rake rocks", and here is why:

* Our Rake build is a lot smarter about build product dependencies. For 
example, if I say 'rake test' and nothing has changed within the ./sql 
directory since the last build, the step for recreating the database is 
skipped. The same can be done with NAnt, however it would make it a lot 
more complex than I would personally be comfortable with (been there 
with a 3 kLOC Ant build once). I think that this feature alone saves 
about an hour of unproductive time per day across the project. Which 
makes it a worthwhile thing right away, and is the main reason why build 
users voluntarily use Rake in their development environments instead of 
NAnt (I keep both builds alive).

* Even when it has to do everything from scratch, our Rake build is 
slightly faster than our NAnt build, despite doing more than NAnt (such 
as checking tkmestamps etc). I half-expected it to be somewhat slower, 
and was afraid to find it much slower. It turns out that I was wrong.

* Custom tasks are very easy to write. E.g., the source for my csc task 
(compiles a FileList of C# sources) is mere 40 lines. Because they are 
so easy to write, it is affordable to have all sorts of small nice 
touches in the build, such as this method:

# Decides where should the database files be placed
def database_path
  return @database_path if @database_path
  path = PROPS['database_path']
  if path == '%default'
    # try to place database on the RAMDrive
    if File.exists?('B:/')
      path = 'B:\Databases'
    else
      path = 'C:\Databases'
    end
  end
 
  mkdir_p path unless File.exists? path
  return @database_path = path
end

Doing the same thing in NAnt build is, again, possible, but I would shy 
away from the extra complexity in this case.

* Custom tasks for Rake are written in the same language as the build 
file itself, require no compilation, and can be included in the build as 
easily as "require 'rake_helpers'".

* Ruby syntax is conveniently non-invasive, so it was trivial to give 
the aforementioned csc task an interface like this:
  csc :out => TEST_DLL,
      :sources => TEST_SOURCES,
      :resources => 'src/test/**/EmbeddedResources/**/*',
      :references => [APP_DLL, WEB_CONTROLS_DLL, 
'tools/nunit/nunit.framework.dll', 'tools/nmock/NMock2.dll', 
'lib/log4net/log4net.dll']

* I can use breakpoint.rb anywhere in the build file, custom tasks file 
or even Rake sources, therefore it tends to be much easier to 
troubleshoot the build problems.

* Since extraction of custom tasks and helper methods into a separate 
file is so easy, the build file itself is considerably shorter than 
Nant's and mostly deals with target dependencies. Not to mention the 
absence of closing XML tags and other such syntactic noise. The end 
result is something  that conveys the big picture (what is built from 
what) much better.

* Finally, the icing on the cake: sh 'tools\nunit.exe ...' prints out a 
new dot after every test, rather than writing six lines of dots at once 
in the end, as Nant does... :)

Morale: if you cannot have Ruby in production code, you may still find 
it useful for project automation and other non-production uses. Speaking 
of which, one day I may write about using ActiveRecord as a way to talk 
to the database in Watir tests. I am actually doing it, but not enough 
to be sure if it really was a good idea yet.

Best regards,
Alexey Verkhovsky

Footnotes:
* My _real_ purpose was adding another .rb file to our CVS, and 
eventually world domination (of course).