Saltar al contenido principal

Apéndice: planificación programática

[Traducción Beta No Oficial]

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

En secciones anteriores vimos cómo usar la CLI de Atlas para generar archivos de migración. Sin embargo, también podemos generar estos archivos programáticamente. En esta sección revisaremos cómo escribir código Go que pueda usarse para planificar automáticamente archivos de migración.

1. Habilitar el flag de función para migraciones versionadas

[Repositorio de soporte]

El cambio descrito en esta sección puede encontrarse en el PR #2 del repositorio de soporte.

El primer paso es habilitar la función de migración versionada pasando el flag sql/versioned-migration. Dependiendo de cómo ejecutes el generador de código de Ent, debes usar una de estas dos opciones:

If you are using the default go generate configuration, simply add the --feature sql/versioned-migration to the ent/generate.go file as follows:

package ent

//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/versioned-migration ./schema

A continuación, vuelve a ejecutar la generación de código:

go generate ./...

Tras ejecutar la generación de código, deberías ver estos métodos añadidos a ent/migrate/migrate.go:

  • Diff

  • NamedDiff

Estos métodos se usan para comparar el estado leído desde una conexión de base de datos o un directorio de migraciones con el estado definido por el esquema de Ent.

2. Script de planificación automática de migraciones

[Repositorio de soporte]

El cambio descrito en esta sección puede encontrarse en el PR #4 del repositorio de soporte.

Base de datos de desarrollo (Dev)

Para poder planificar archivos de migración precisos y consistentes, Atlas introduce el concepto de Dev database, una base de datos temporal que se usa para simular el estado de la base de datos tras diferentes cambios. Por lo tanto, para usar Atlas y planificar migraciones automáticamente, necesitamos proporcionar una cadena de conexión a dicha base de datos a nuestro script de planificación. Normalmente, esta base de datos se crea usando un contenedor Docker local. Hagámoslo ahora ejecutando el siguiente comando:

docker run --rm --name atlas-db-dev -d -p 3306:3306 -e MYSQL_DATABASE=dev -e MYSQL_ROOT_PASSWORD=pass mysql:8

Usando la base de datos de desarrollo que acabamos de configurar, podemos escribir un script que use Atlas para planificar archivos de migración. Creemos un nuevo archivo llamado main.go en el directorio ent/migrate de nuestro proyecto:

ent/migrate/main.go
//go:build ignore

package main

import (
"context"
"log"
"os"

"<project>/ent/migrate"

atlas "ariga.io/atlas/sql/migrate"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql/schema"
_ "github.com/go-sql-driver/mysql"
)

const (
dir = "ent/migrate/migrations"
)

func main() {
ctx := context.Background()
// Create a local migration directory able to understand Atlas migration file format for replay.
if err := os.MkdirAll(dir, 0755); err != nil {
log.Fatalf("creating migration directory: %v", err)
}
dir, err := atlas.NewLocalDir(dir)
if err != nil {
log.Fatalf("failed creating atlas migration directory: %v", err)
}
// Migrate diff options.
opts := []schema.MigrateOption{
schema.WithDir(dir), // provide migration directory
schema.WithMigrationMode(schema.ModeReplay), // provide migration mode
schema.WithDialect(dialect.MySQL), // Ent dialect to use
schema.WithFormatter(atlas.DefaultFormatter),
}
if len(os.Args) != 2 {
log.Fatalln("migration name is required. Use: 'go run -mod=mod ent/migrate/main.go <name>'")
}
// Generate migrations using Atlas support for MySQL (note the Ent dialect option passed above).
err = migrate.NamedDiff(ctx, "mysql://root:pass@localhost:3306/dev", os.Args[1], opts...)
if err != nil {
log.Fatalf("failed generating migration file: %v", err)
}
}
información

Observa que necesitas hacer algunas modificaciones en el script anterior en las líneas resaltadas. Edita la ruta de importación del paquete migrate para que coincida con tu proyecto y proporciona la cadena de conexión a tu base de datos de desarrollo.

Para ejecutar el script, primero crea un directorio migrations dentro de ent/migrate en tu proyecto:

mkdir ent/migrate/migrations

Luego, ejecuta el script para crear el archivo de migración inicial de tu proyecto:

go run -mod=mod ent/migrate/main.go initial

Fíjate que initial aquí es solo una etiqueta para el archivo de migración. Puedes usar cualquier nombre que desees.

Observa que tras ejecutar el script, se crearon dos nuevos archivos en el directorio ent/migrate/migrations. El primer archivo se llama atlas.sum, que es un archivo de suma de comprobación que Atlas usa para garantizar un historial lineal de migraciones:

ent/migrate/migrations/atlas.sum
h1:Dt6N5dIebSto365ZEyIqiBKDqp4INvd7xijLIokqWqA=
20221114165732_initialize.sql h1:/33+7ubMlxuTkW6Ry55HeGEZQ58JqrzaAl2x1TmUTdE=

El segundo archivo es el archivo de migración propiamente dicho, que lleva el nombre de la etiqueta que pasamos al script:

ent/migrate/migrations/20221114165732_initial.sql
-- create "users" table
CREATE TABLE `users` (`id` bigint NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `email` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE INDEX `email` (`email`)) CHARSET utf8mb4 COLLATE utf8mb4_bin;
-- create "blogs" table
CREATE TABLE `blogs` (`id` bigint NOT NULL AUTO_INCREMENT, `title` varchar(255) NOT NULL, `body` longtext NOT NULL, `created_at` timestamp NOT NULL, `user_blog_posts` bigint NULL, PRIMARY KEY (`id`), CONSTRAINT `blogs_users_blog_posts` FOREIGN KEY (`user_blog_posts`) REFERENCES `users` (`id`) ON DELETE SET NULL) CHARSET utf8mb4 COLLATE utf8mb4_bin;

Otras herramientas de migración

Atlas se integra muy bien con Ent, pero no es la única herramienta de migración que puede usarse para gestionar esquemas de bases de datos en proyectos Ent. La siguiente es una lista de otras herramientas de migración compatibles:

Para aprender más sobre cómo usar estas herramientas con Ent, consulta la documentación sobre este tema.