Rake is a simple build program. You can use it to automate complex or repetitive tasks. It is written in Ruby, but is useful in far more than just Ruby projects.
The great news is that if you have Ruby on your system, you probably already have Rake. It has been included as part of the standard Ruby distribution for a few years.
It is easy to test which version of Rake you have from the command line:
If you do not have Rake, then you just need to install a fresh release of Ruby. Go ahead. I’ll wait.
Rake is driven by a Rakefile. A Rakefile is a collection of Ruby instructions organized into tasks.
This is not going to be an in-depth Rake tutorial. I’ve noticed a lack of simple real-world Rakefile examples, aside from one excellent Rake introduction. I have a Rakefile I need to build. That makes this a good opportunity for me to write a page about Rake.
Building a Simple Rakefile
I have a Web site. You may have noticed that. If you only know me from my frequent postings on social network sites like Plurk or Google+. I assure you that I do indeed have a Web site.
The thing about my Web site is that rather than use Drupal or some other convenient Content Management System, I use a tool that generates static HTML. The static HTML and associated files like images and stylesheets are then uploaded to an inexpensive Web host. Hey. It works for me. Static HTML serves fast, and I don’t change the content on my site that often.
I invoke a simple command to build my site before uploading it.
That is not painful, but it does get boring. More importantly, I have been thinking about how Compass would be a great thing to use for my site. But site-builder.py
is an ugly, ugly piece of hackery. It is just coherent enough to build the site you’re reading. It is certainly not up to the job of driving Compass. That’s where Rake comes in.
One Task
You might want to use the exact same Rake tasks as me while you read this. Here is a dummy version of site-builder.py
that you can use. No, it does not build a site. It will give you something to work with for demonstrating Rake, though.
First I will start by creating a Rakefile to handle my current workflow.
The simplest Rake task
command takes two arguments: a name for that task, and a block of actions to perform when that task is requested. The name can be written as a String or as a Symbol, but I usually see it written as a Symbol.
The block can be any valid Ruby code. The :html
block uses my shell to run the Python script that builds coolnamehere.com. You ask Rake to execute a particular task from the command line by using the task’s name.
How do you find out what tasks are available, aside from reading the Rakefile? The -T flag will ask Rake to list all of the available tasks.
Oh. Hold on a second. Rake will only list the tasks you have described with the desc
command.
Let us try that again. The -T
flag will ask Rake to list all of the available described tasks.
A Rakefile can have many tasks, but some of them may be utility tasks which are not expected to be called by the user. That is why limiting the task list to described tasks is a good idea.
A Second Task
As I mentioned before, part of the reason I am writing a Rakefile is because I want to use Compass to define the styles for coolnamehere. I set up a Compass project parallel to my site sources, including the blueprint module. The Compass project is called “style”. My projects generally do not have clever names.
If you really want to play along, here is how I set up my Compass project.
This is another straightforward task.
I do not expect anything exciting to happen, since I have not changed the SCSS files.
There is still a problem, though. All of the stylesheets are in style/stylesheets
, but the working stylesheets have been over in site/inc/css
. I need Rake to copy the finished stylesheets to the expected location. Might as well copy the images that are sitting in the style
project while I am at it.
Rake conveniently imports the FileUtils module. This lets me use Ruby standard library methods such as cp
to copy a list of files rather than relying on platform-specific shell commands.
What does that look like in action?
Good enough. Excuse me while I adjust my HTML template to point at the right stylesheets.
Setting a Dependency
There are already awkward bits to the Rakefile as it is right now. I need to run two commands in order to build the site completely. Because site-builder.py
also copies the site files to a new location, I must also remember to run the commands in the correct order. If I don’t, then the generated CSS will go into my site sources after the HTML has already been generated and copied.
What if I made :css
a dependency of :html
? Rake would make sure that the :css
task was executed before it tried to execute the :html
task.
A little syntax trickery simplifies the task of describing a task’s dependencies.
Now instead of just a name for the task, we are giving task
a Hash. The only key of that Hash is the name of the task, and the value is a list of tasks which this one depends on.
Excellent. Now I can generate both CSS and HTML from a single Rake command. I am going to work a little bit on the styles, and to see if I notice any other little issues with my Rakefile.
Setting The Default Task
It has been pretty effective so far. Incidentally, Compass is kind of awesome. I highly recommend you check it out for your Web design needs.
It would be nice if I could make the rake
call a little shorter, though. I have a shortcut set up in Vim that invokes Rake with a default argument. It would be nice to use that shortcut while I am working on coolnamehere.
Rake already has rules for default tasks, actually. It looks for a task named “default” or :default
. That makes sense. Let me set up a default task that depends on the :html
task.
That is all I need to do, actually. A task can simply be a name and its dependencies. You do not need to define a block of actions for that task.
Something I Have Been Meaning To Get Around To
I have been promising myself for years that I will assemble some sort of script that would automate the process of uploading my site. I never get around to it, though. Instead I fire up NCFTP, load the “coolnamehere” bookmark I’ve had for years, and upload.
It is time to fix that by adding an “upload” task. I will take advantage of the syncftp Ruby library, which looks like it will handle all of the little details.
For the first test, I will just fill in the blanks using the syncftp README as a guide.
Conclusion
Here’s the complete Rakefile, with the as-yet untested “upload” task.
Well, yes. There are differences from the actual Rakefile, but this gets the idea across.
All that I need to do now is test it.
Backlinks
Added to vault 2024-01-15. Updated on 2024-07-10