Simple Passive Code Generation

TL;DR – Here’s a rake task you can use to easily generate classes:

desc 'generate a class in lib/ and a spec in spec/lib/ for name=underscored_class_name'
task :genclass do
  require 'erb'

  filename = ENV['name']
  raise 'must specify name=underscored_class_name' unless filename
  classname = filename.camelize

  class_file_template = <<-EOF
class <%= classname %>

  def something

  spec_file_template = <<-EOF
require 'spec_helper'

describe <%= classname %> do

  before do
    @target = <%= classname %>.new

  describe '#something' do
    it "should do something"

    ["lib/#{filename}.rb",           class_file_template],
    ["spec/lib/#{filename}_spec.rb", spec_file_template]
  ].each do |(fname, template)|
    if File.exists?(fname)
      puts "skipping generation of existing file - #{fname}"
      puts "generating #{fname}", 'w+') do |f|
        f.write template.result(binding)

Now, it’s story time:

The first time I used Ruby on a “real” project was to create a code generator for C# classes and their corresponding unit tests. Like the controller and model generators in Rails, these scripts saved us time that would have otherwise been spent fumbling through the maze of tree views and context menus in Visual Studio, letting us instead focus on the abstractions we were bringing to life. We felt so much more productive due to the code generating and project file manipulation tools we made on this project in Ruby that we referred to our Ruby tools as The Power — a deliciously nerdy reference to The One Power from The Wheel of Time series.

While working on a Padrino app recently, I found myself wanting for a simple vanilla class generator, for into a model, controller, or view does not all code belong.

On Rails projects in the past, I would create my own generators using whatever manifest definition and overlay directories were being used at the time. Rails has very nice support for custom code generators. Padrino’s generators, however, seemed a bit more difficult to extend and customize at a glance — more difficult, at least, than writing a simple one from scratch, which is exactly what I decided to do.

It’s a good reminder that as a developer, you should always be looking for ways to use the tools you have to reduce the time you spend doing mindless, repetitive, and error-prone tasks. In other words — whenever you can, use The Power to save time.