Maintaining database column order with migrations

If you’re anything like me, you like to keep database columns in a reasonably logical order. In my case I generally keep primary keys as the first column, then content columns, then special usage columns, then foreign keys e.g.

id
name
description
created_on
updated_on
account_id

Now, say I added a ‘slug’ column with a migration:

def self.up
  add_column "projects", "slug", :string
end

That’s fine, I have my new column but it’s after my foreign keys:

id
name
description
created_on
updated_on
account_id
slug

What’s it doing down there? I want it after the ‘name’ column! …wouldn’t it be nice if you could specify an :after option for add_column.
We can make this possible by monkey patching the add_column method at the top of our migration file (I will make this into a plugin when I get time):

module ActiveRecord
  module ConnectionAdapters # :nodoc:
    module SchemaStatements
      def add_column(table_name, column_name, type, options = {})
        add_column_sql = "ALTER TABLE #{table_name} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
        after_column = options.delete(:after)
        add_column_options!(add_column_sql, options)
        add_column_sql << " AFTER #{after_column}" if after_column
        execute(add_column_sql)
      end
    end
  end
end

This lets us do the following:

def self.up
  add_column "projects", "slug", :string, :after => 'name'
end

Which gives us:

id
name
slug
description
created_on
updated_on
account_id

Much better… this may seem a little petty, however as your tables get more and more columns it makes things much easier to follow.
Please note: I have only tested this with MySQL
h4. Update: this is now a plugin and can be “downloaded here”:http://svn.soniciq.com/public/rails/plugins/iq_migration_extensions/

CSS and JS directories in Rails

One thing that annoyed me when I first started using Rails at 0.14 was that I was forced to put my .css files in a ‘stylesheets’ directory and my .js files in a ‘javascripts’ directory.
Previous to Rails I would put .css files in a ‘css’ directory and .js files in a ‘js’ directory (call me old fashioned). I use the following code in my application helper to allow me to do this:

module ApplicationHelper
  def javascript_path(source) compute_public_path(source, 'js', 'js') end
  def stylesheet_path(source) compute_public_path(source, 'css', 'css') end
end

Just incase anyone else has the same niggle.
*Update 29-11-08:* for Rails 2.2, see new post.

Disabling plugin code in generators/migrations

I have found on numerous occasions that I need to disable certain plugin functionality if running a generator / rake db:migrate etc.
An easy way to disable certain functionality follows:

def method_that_shouldnt_be_run_in_migrations_or_generators
  # Return if we are using a generator or migrations
  script = File.basename($0)
  return if (script == 'generate') || (script == 'rake' && ARGV[0] =~ /migrate$/)
end