How to Write a Rake Task

Since I switched to Jekyll, I lost out on the nice Rake tasks that Octopress provided. That's okay though. I thought this would be a good opportunity to actually write a Rake task for myself.

What's a Rake task?

Rake is Ruby's version of make files (r + make = Rake, get it?). A Rakefile just includes executable Ruby code, so you can encapsulate tasks that you end up using a lot. You could also hook up Rake with a task runner in order to run processes on a schedule.

But let's not get ahead of ourselves.

Since I end up having to copy and paste a lot of the same boilerplate when writing a new post, wrapping that procedure into a Rake task sounds like a great idea.

Rake setup

It's pretty easy to set up a Rake task for your app. Just consult the documentation!

Or you could do the super pared down version that I did.

Just gem install rake. Then touch Rakefile in the top-level directory for your app. Within the Rakefile is where the tasks go. You could namespace your tasks, but since I only need one for now, I did not.

I wrote a task called new_post that takes an argument of the title and uses the date and title to generate a new markdown file in the _posts directory. The hardest part was figuring out how to parse the arguments. You could pass in command line arguments with the VARIABLE=VALUE syntax, or you could also pass them in as an array.

I chose to go the more contemporary array method. and thus ended up with this script:

require 'rake'
require 'date'

desc 'generates a new post'
task :new_post, [:title] do |t, args|
  date = Time.now

  if args[:title].nil?
    puts "Please enter a title:"
    title = STDIN.gets.chomp
  else
    title = args[:title]
  end
  formatted_title = title.downcase.split(" ").join("-")

  post_title = "#{date.strftime('%Y-%m-%d')}-#{formatted_title}.markdown"
  contents = <<-STR 
---
layout: post
title: "#{title}"
date: #{date.to_s} 
comments: true
categories: 
---
  STR

  File.open("_posts/#{post_title}", "w") do |f|
    f.write(contents)
  end
  puts "New post: #{title} generated"
end

Here, I'm parsing the title and turning it into a slug of sorts for the file name. I'm also doing the same with the date. And then I'm writing the boilerplate Jekyll post contents as a heredoc. I'm also using Ruby's File abstraction in order to manage the creation and writing of the file. More details here.

To run the task from the command line, just type rake new_post['title goes here'] and a new post will be generated. I'm also handling the case that I forgot to pass in the title explicitly, which honestly seems pretty likely, so I check if the title argument is empty and prompt for a title in that event.

Anyway, this is working well enough for me, so I think I'll leave it until I need something more robust. And that's Rake tasks in a nutshell.

Additionally, I included a description of desc 'generates a new post' right above the definition of my task so that the tasks will be listed when I run rake -T. That's another best practice to keep your code well-documented.