Rake db:rollback

Friday, June 29

Whenever I create a new migration I want to make sure my down method works as well as my up. So, I always end up doing rake db:migrate, check the current version number, n, and then roll it back one using rake db:migrate VERSION=n-1. Sometimes I’m migrating up more than one version, so I want to roll back a few steps (rake db:migrate VERSION=n-3). This, of course, is cumbersome. So, I wrote a simple task to make it easier:

namespace :db do
  desc 'Rolls the schema back to the previous version. Specify the number of steps with STEP=n'
  task :rollback => :environment do
    step = ENV['STEP'] ? ENV['STEP'].to_i : 1
    version = ActiveRecord::Migrator.current_version - step
    ActiveRecord::Migrator.migrate('db/migrate/', version)
  end
end

This lets me migrate up, and roll back to the previous version easily.

$ rake db:migrate
$ rake db:rollback

And I can go back a certain number of steps just as easily.

$ rake db:rollback STEP=3

Hopefully somebody will find this as useful as I do.

Generating a SPECDOC from tests in Rails

Thursday, March 29

So I’ve been using RSpec for a while, but sometimes its integration with the Rails framework frustrates me. On the last project I started, I decided not to make waves and just use Test::Unit, which is the Rails default. It’s just easier that way.

Still, there are some things I like about RSpec. One of these things is the ‘this should do that’ syntax, which feels more natural to me. So, ever since I’ve been back on the Test::Unit bandwagon, I’ve been writing by tests in a test_should_do_something_amazing style. (I’ve noticed that a lot of Rails developers are using this style as of late, and even the test stubs that the Rails generators spit out are using this style as well).

Another thing I like about RSpec is its ability to produce a specification document based on your tests, which it calls a SPECDOC. Inspired by the recently added rake task notes, (which enumerates all the commented fixmes, todos, etc. in your app), I figured a SPECDOC enumerator wouldn’t be too hard to add. Here’s a stab at a rake task that does the job. This will rip through your tests, look for specification-style tests, and generate a SPECDOC in the docs directory.

desc "Generate specdoc-style documentation from tests" 
namespace :doc do
  task :specs do
    puts 'Started'

    timer, count = Time.now, 0

    File.open(RAILS_ROOT + '/doc/SPECDOC', 'w') do |file|
      Dir.glob('test/**/*_test.rb').each do |test|
        test =~ /.*\/([^\/].*)_test.rb$/
        file.puts "#{$1.gsub('_', ' ').capitalize} should:" if $1
        File.read(test).map {|line| /test_should_(.*)$/.match line }.compact.each do |spec|
          file.puts " * #{spec[1].gsub('_', ' ')}" 
          sleep 0.001; print '.'; $stdout.flush; count += 1
        end
        file.puts
      end
    end

    puts "\nFinished in #{Time.now - timer} seconds.\n" 
    puts "#{count} specifications documented" 
  end
end

Place this snippet in a file called specdoc.rake and throw it in lib/tasks and you’ll be good to go. Run it using rake doc:specs as follows:

$ rake doc:specs
Started
..............................................................................
..............................................................................
......................................
Finished in 2.308674 seconds.

194 specifications documented

The dots and chatter are all just eye-candy, but I thought I’d add them in for good measure. I’m thinking of removing it, though, just to cut down on the code. The SPECDOC will be output to the doc directory.

$ cat doc/SPECDOC 
Memberships controller should:
 * require login for protected actions
 * not require login for public actions
 * create and send invitations

Users controller should:
 * create user
 * require unique login on create
 * require password on create
 * require password confirmation on create
 * require email on create
 * require valid email on create
 * require authentication
 * accept authentication
 * get new user
 * show user
 * update user
...

Note that this will only document tests that begin with the aforementioned test_should_ prefix. Test cases that don’t use this convention are ignored, though you could tweak the regex to include them.

My regex-fu may be lacking, so if anyone has any suggestions for how I could make this better, don’t hesitate to pipe up.

rake db:version

Tuesday, September 26

I often find myself needing to know what migration version my database is at. There is the ./script/about script, which tells me the version number (and a host of other things), but I don’t want to have to look through all that. All I want is the migration number I’m currently at.

Here is a simple rake task you can plop in your lib/tasks directory that will print the current version.


# lib/tasks/db_migration_version.rake
namespace :db do
  desc 'Print the current database migration version number'
  task :version => :environment do
    puts ActiveRecord::Migrator.current_version
  end
end

Example usage:

$ rake db:version
29

Fun!