---
title: The defest of leppards
teaser:
tags: web,rails,postgresql
author: Matt Jankowski
published_on: 2008-01-14
---

If you have any moderately old rails applications in production, and you find
yourself screwing around with indexes in newer migrations, keep in mind that the
index naming convention rails uses changed at some point (specifically, in
[changeset 4768](http://dev.rubyonrails.org/changeset/4768)).

So if you had this in an application from a while ago - specifically, if you
have an application that was in production prior to the 1.2 release of rails -
and you have a migration like this...

```ruby
# db/migrate/097_add_title_url_to_articles
class AddTitleUrlToArticles < ActiveRecord::Migration
  def self.up
    add_column :articles, :title_url, :string
    add_index :articles, :title_url
  end
  def self.down
    remove_column :articles, :title_url
  end
end
```

...and as part of regular maintenance you create a migration like this...

```ruby
# db/migrate/297_add_indexes_to_articles
class AddIndexesToArticles < ActiveRecord::Migration
  def self.up
    remove_index :articles, :site_id
    remove_index :articles, :title_url
    add_index :articles, [:site_id, :title_url]
  end
  def self.down
    remove_index :articles, [:site_id, :title_url]
    add_index :articles, :title_url
    add_index :articles, :site_id
  end
end
```

![''](http://images.thoughtbot.com/ui/2008-1-14-2e_26.JPG "Nothing to do with
rails, or migrations.")

...assuming that you have entirely dropped and rebuilt your development
environment database at some point since you wrote the original migration (which
may be quite some time ago, at this point) - the migrations will run fine, and
your local development database will have the indexes you want it to.

However, when it's time to go to production, and you're dealing with a database
on the live cluster which has **not** been reset/rebuilt/whatever since it's
initial deployment (because seriously...why would it have?), you will find that
migration #297 does not run against the production data because the application
will try to use a different name than what it originally used when it was
running an older version of rails with the former naming style.  Hmmm.

This is not a problem though, rails gives us a :name option on indexes in
migrations.  You can change your new migration to reference what you know the
old indexes were called...

```ruby
# db/migrate/297_add_indexes_to_articles
class AddIndexesToArticles < ActiveRecord::Migration
  def self.up
    # The indexes below were made with "old style" database index naming
    remove_index :articles, :name => :articles_site_id_index
    remove_index :articles, :name => :articles_title_url_index
    add_index :articles, [:site_id, :title_url]
  end
  def self.down
    remove_index :articles, [:site_id, :title_url]
    # Restore indexes with "old style" naming
    add_index :articles, :title_url, :name => :article_title_url_index
    add_index :articles, :site_id, :name => :article_site_id_index
  end
end
```

...but wait!  You're not done.

Even though you can deploy now and the production database will run the
migrations successfully, what about the new developers coming onto the project
who are going to be building a database from scratch?  Now we need to go modify
the old migration so that it produces an index named the way the indexes were
originally named back in the time that they were actually run on the production
server, using that earlier version of the application and of rails.

```ruby
# db/migrate/097_add_title_url_to_articles
class AddTitleUrlToArticles < ActiveRecord::Migration
  def self.up
    add_column :articles, :title_url, :string
    add_index :articles, :title_url, :name => :articles_title_url_index
  end
  def self.down
    remove_column :articles, :title_url
  end
end
```

This is all sort of annoying, and violates the never commit a change to an old
migration rule.  However, since the framework doesn't handle it for you, you get
to handle it for yourself.
