Migraciones vs cargar el DB Schema

  • por Thomas Hepner

Es bastante frecuente ver casos de aplicaciones desarrolladas en Ruby on Rails que son difíciles de poner en producción, o bien de replicar en otras máquinas. Si bien esto puede deberse a un sinfín de razones, en esta ocasión dedicaremos nuestra atención a una parte crucial de toda aplicación web: la base de datos. 

Entre las tantas convenciones que nos ofrece Rails, se podría decir que una de las más importantes es la implementación de la clase ActiveRecord, un patrón de diseño que ofrece un wrapper de una tabla de la base de datos, con acceso a sus distintos atributos y métodos para poder crear, editar o destruir registros. Si bien existe una corriente de desarrolladores que critica ActiveRecord y la forma en que quita control sobre el manejo de datos, su uso apuesta por un desarrollo más ágil de aplicaciones web, y seguir sus convenciones podría permitir alcanzar un producto mínimo viable de forma más rápida y menos riesgosa que con otras tecnologías.

La forma en la que ActiveRecord va alterando el esquema de la base de datos es a través de migraciones. Una migración es un método que permite llevar a la base de datos desde un estado consistente a otro, ejecutando scripts en Ruby de manera que el desarrollador no tenga que escribir SQL (apostando por mantener todo el código en el mismo lenguaje). El ejemplo típico de una migración se puede ver a continuación:

class CreateProducts < ActiveRecord::Migration[5.0]
  def change
    create_table :products do |t|
      t.string :name
      t.text :description
 
      t.timestamps
    end
  end
end

Sin ir más allá, este fragmento logra llevar a la base de datos desde un esquema sin la tabla Products hacia uno en el cual está creada, y viceversa. Esto último significa que, mediante un método rollback, es posible volver al estado consistente más reciente. Todo esto es muy conveniente y ordenado.

Sin embargo, ¿qué pasa cuando la cantidad de migraciones de una aplicación aumenta demasiado? Si están bien hechas, ejecutarlas todas debería llevar hasta el esquema consistente más reciente de la base de datos. Pero el problema de las migraciones es que, al ejecutar el comando rake db:migrate de Rails al poner en marcha por primera vez una aplicación provoca que se ejecuten todas las migraciones. Esto puede consistir en una gran cantidad de operaciones sobre la base de datos, pues pasa uno a uno por todos los estados consistentes de la base de datos, repitiendo su historia paso a paso. Ejecutar todas esas migraciones, o bien dejar espacio para que sean modificadas, introduce riesgos importantes que pueden llevar a una replicación incorrecta de la aplicación.

Lo más conveniente entonces es simplemente construir el último estado consistente de la base de datos, o cargar el esquema de datos actual de la aplicación. Esto ahorra una cantidad importante de operaciones, además de eliminar el riesgo que suponen migraciones corruptas (que pueden darse con regularidad en proyectos de software donde interactúan muchos desarrolladores a la vez). Rails ofrece un rake task para realizar esto: rake db:schema:load, que carga el esquema de la base de datos sin necesidad de ejecutar todas las migraciones.

Hay solo una particularidad con este último método: al ejecutarse, elimina todos los registros de la base de datos, por lo que solo debería usarse para poner una aplicación en producción desde cero, no para actualizar su esquema cuando ya está en marcha. Si se usa correctamente, este método permite mantener las migraciones solo para ambientes de desarrollo en los que sean estrictamente necesarias.

¿Qué es necesario para usar rake db:schema:load? Es necesario que esté presente el archivo db/schema.rb. Se recomienda fuertemente que este archivo se encuentre incluido en el sistema de control de versiones del proyecto. Sin embargo, en caso de no estar, se puede generar fácilmente usando el comando rake db:schema:dump

La recomendación final es la siguiente: una vez que un proyecto se hace más grande y difícil de manejar, no tengas miedo de deshacerte de migraciones viejas, hacer un dump del esquema de la base de datos, y continuar desde ahí. Siempre y cuando tengas cuidado de no eliminar los datos en producción, esta forma de mantener tu base de datos puede ahorrarte costos y tiempo valiosos.

Referencias

thumbnail