Saturday, October 07, 2006

Rake: Tasks with parameters

I've written several Rake tasks in the past that could have been improved by accepting parameters, but I never knew how to make it work. It's not that I thought it was impossible to pass parameters to Rake tasks, I just never bothered to figure out how. Lucky for me, a teammate recently took the time to figure it out. Today I'm changing an existing rakefile to take advantage of passing in parameters.

The file now:
require 'writer'
require 'html_writer'
require 'doc_writer'

directory "built_docs"
directory "built_html"

task :doc => [:built_docs, :clean_doc] do
Dir['chapters/*.txt'].each do |chapter|
output = "built_docs/#{File.basename(chapter,'txt')}doc"
File.open(output, 'w') { |file| DocWriter.new(file).write(chapter) }
puts "generated #{output}"
system "chmod 444 #{output}"
end
end

task :html => [:built_html, :clean_html] do
Dir['chapters/*.txt'].each do |chapter|
output = "built_html/#{File.basename(chapter,'txt')}html"
File.open(output, 'w') { |file| HtmlWriter.new(file).write(chapter) }
puts "generated #{output}"
system "chmod 444 #{output}"
end
end

task :clean_doc do
Dir['built_docs/*'].each do |output|
rm output
end
end

task :clean_html do
Dir['built_html/*'].each do |output|
rm output
end
end
Clearly, this file is not near as DRY as it could be.

The first step is to create a new task that will generate output and accept the format as an argument.
task :default do
unless ENV.include?("output") && (ENV['output']=='doc' || ENV['output']=='html')
raise "usage: rake output= # valid formats are [html] or [doc]"
end
format = ENV['output']
puts format
rm_rf format
mkdir format
end
The above code verifies that a valid format is specified. It also removes the need for both the directory and clean tasks. The only work left to do is combine the output generation tasks.
task :default do
unless ENV.include?("output") && (ENV['output']=='doc' || ENV['output']=='html')
raise "usage: rake output= # valid formats are [html] or [doc]"
end
format = ENV['output']
puts format
rm_rf format
mkdir format
Dir['chapters/*.txt'].each do |chapter|
output = "#{format}/#{File.basename(chapter,'txt')}#{format}"
writer = (format=='doc' ? DocWriter : HtmlWriter)
File.open(output, 'w') { |file| writer.new(file).write(chapter) }
puts "generated #{output}"
system "chmod 444 #{output}"
end
end
The resulting task is cleaner and easier to maintain.

Running the new task from the command line: focus:~ jay$ rake output=html
Post a Comment