Rails: renumerando migrations

Migrations são um recurso muito interessante to Rails pra criação incremental de esquemas de banco de dados relacional. As migrations, como tudo no Rails, são arquivos Ruby numerados que são executados na ordem da numeração pra criar o banco de dados.

Cada migration tem a seguinte cara:

class CreatePeople < ActiveRecord::Migration
  def self.up
    create_table :people do |t|
      t.column :name,                :string
      t.column :birth_date,          :datetime
    end
  end
  def self.down
    drop_table :people
  end
end

Note três coisas:

  1. as tabelas são declaradas usando uma DSL de alto nível em Ruby
  2. como você não precisa usa a DDL específica do banco de dados, as migrations funcionem em qualquer banco suportado pelo Rails.
  3. você pode usar coisas específicas de algum banco de dados, se você quiser (mas sua aplicação vai ficar dependente desse banco de dados).

As migrations são criadas automaticamente quando uma classe de modelo é gerada. A migration acima, se tiver sido por exemplo a décima a ser criada, vai estar no arquivo db/migrate/010_create_people.rb.

O "problema" é quando você precisa apagar uma migration que não tenha sido a última a ser criada, sua ordem fica com buracos. Pra resolver isso basta mandar o comando a seguir de dentro do diretório db/migrate:

$ ls -1 | ( i=1; while read IN; do echo mv $IN $(echo $IN | sed -e "s/^[0-9]\+/$(printf '%03d' $i)/") ; i=$[$i + 1]; done)

Esse comando gera a sequência de comandos mv necessários pra refazer a numeração sem buracos. É só pegar a saída dele e colar de novo no shell, ou melhor, passar o comando original por pipe pra sh, ou melhor ainda, tirar o echo e deixar os comandos rolarem direto.

Se você estiver usando controle de versão, Subversion por exemplo, você pode modificar o comando pra colocar svn mv no começo de cada linha ao invés de só mv.