Usando modelos em migrações Rails

De vez em quando, somos tentados a usar modelos em migrações de trilhos. Essa ideia engenhosa, no entanto, acaba sendo uma armadilha, pois o ciclo de vida do código (modelo, neste caso) não corresponde necessariamente ao das migrações. Um exemplo é dado pelo Rails Guide mostrando como criar um modelo local dentro da migração para evitar tais conflitos.

Outro exemplo seria renomear um nome de modelo (por exemplo, de class Item < ActiveRecord::Basepara class Product < ActiveRecord::Base) e sua tabela correspondente. Isso interromperia todas as migrações anteriores que utilizavam esse modelo. Por exemplo, a migração seguinte seria interrompida:

class SomeMigration < ActiveRecord::Migration
method
def
items
= Item.all
...
end
end

Note que neste ponto a tabela itemsjá existe (desde a nova migração, que muda de nome tem naturalmente um timestamp maior e deve ser executada após esta migração) e usando SQL puro (ou respectivo DB DSL) usando execute(como alguns podem propor) pode evitar que todas essas migrações sejam interrompidas:

class SomeMigration < ActiveRecord::Migration
method
def
execute
<< -SQL
...
SELECT
"items".* FROM "items"
...
SQL

end
end

Isso, no entanto, cria um novo problema:

  • Mudar para outro banco de dados (por exemplo, MySQL para PostgreSQL) exige a reescrita de todas as migrações, incluindo esses códigos. Em outras palavras, o sistema não é mais agnóstico de DB
  • A conveniente Active Record Query Interface (por exemplo ActiveRecord.find) não pode mais ser usada.

A melhor solução (que encontrei até agora) é criar um modelo genérico na migração e fazer com que ele acesse uma tabela específica:

class SomeMigration < ActiveRecord::Migration

class GenericModel < ActiveRecord::Base
self.table_name = 'items'
end

method
def
GenericModel.find ...
...
end
end

Dessa forma, podemos conservar o recurso agnóstico de DB do RoR e aproveitar a rica interface de consulta sem temer modificações futuras no modelo.


Isenção de responsabilidade: esta solução é uma versão modificada de “Como usar modelos em suas migrações (sem matar gatinhos)”