Saltar al contenido

Sembrando una Base de Datos en Ruby on Rails

ALT

David Morales

Photo por Jeremy Bishop en Unsplash

Ruby on Rails tiene herramientas excelentes para sembrar una base de datos (rellenarla con datos), y gracias al trabajo de la comunidad, muchas gemas hacen esta tarea más fácil.

Aparte de sembrar una base de datos, tenemos herramientas útiles para comprobar la base de datos y organizar mejor las semillas de datos.

Creando una aplicación de ejemplo

Empecemos creando una aplicación nueva.

rails new ejemplo cd ejemplo
Lenguaje del código: Shell Session (shell)

Creando un modelo

Después, genera un modelo nuevo. Si tienes curiosidad, tecleando rails generate (o el atajo rails g), verás todos los generadores disponibles.

rails g model Pelicula titulo director sinopsis:text vista_en:date
Lenguaje del código: Shell Session (shell)

Aquí estás definiendo el título y director como cadenas (el tipo por defecto si no se especifica), sinopsis como texto, y vista_en como fecha (cuando se definen fechas, sin hora, la convención es añadir on al nombre).

Rails generará una migración por ti adaptada a la base de datos por defecto, que es SQLite. Las migraciones son guardadas en db/migrate. ¡Veamos cómo es!

class CreatePeliculas < ActiveRecord::Migration[6.1] def change create_table :peliculas do |t| t.string :titulo t.string :director t.text :sinopsis t.date :vista_en t.timestamps end end end
Lenguaje del código: Ruby (ruby)

Como puedes ver, Rails añade la versión que estás usando entre corchetes al final de la clase padre.

La directiva de timestamps generará los campos created_at y updated_at automáticamente. Muy útil.

Vamos a ejecutarlo.

$ rails db:migrate == 20210311174407 CreatePeliculas: migrating ===================================== -- create_table(:peliculas) -> 0.0020s == 20210311174407 CreatePeliculas: migrated (0.0021s) ============================
Lenguaje del código: Shell Session (shell)

Ahora Rails ha creado la tabla. Por si acaso te has equivocado en algo, siempre puedes volver atrás:

$ rails db:rollback == 20210311174407 CreatePeliculas: reverting ===================================== -- drop_table(:peliculas) -> 0.0019s == 20210311174407 CreatePeliculas: reverted (0.0064s) ============================
Lenguaje del código: Shell Session (shell)

Este comando acepta un parámetro step opcional para volver atrás tantas migraciones como necesites.

Como ya está creada, vamos a ver cómo está el esquema en db/schema.rb:

ActiveRecord::Schema.define(version: 2021_03_11_174407) do create_table "peliculas", force: :cascade do |t| t.string "titulo" t.string "director" t.text "sinopsis" t.date "vista_en" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end end
Lenguaje del código: Ruby (ruby)

¡Bien! Este archivo contendrá el esquema entero de la base de datos a medida que vayamos haciendo migraciones.

Comandos de Rails

¿Cómo puedes saber los comandos de Rails que hay disponibles? Usando el parámetro -T puedes ver una lista:

rails -T
Lenguaje del código: Shell Session (shell)

Incluso puedes filtrar por espacio de nombre, como db:

rails -T db
Lenguaje del código: Shell Session (shell)

Creando algunas semillas

Vamos a la parte interesante de este artículo. Abre el archivo db/seeds.rb, y pega esto:

Pelicula.destroy_all Pelicula.create!([{ titulo: "Soul", director: "Pete Docter", sinopsis: "Un músico que ha perdido su pasión por la música es transportado fuera de su cuerpo y debe encontrar el camino de regreso con la ayuda de un alma infantil que aprende sobre sí misma.", vista_en: 1.week.ago }, { titulo: "El Señor de los Anillos: La Comunidad del Anillo", director: "Peter Jackson", sinopsis: "En la adormecida e idílica Comarca, un joven hobbit recibe un encargo: custodiar el Anillo Único y emprender el viaje para su destrucción en las Grietas del Destino.", vista_en: 2.years.ago }, { titulo: "Terminator 2", director: "James Cameron", sinopsis: "Arnold Schwarzenegger es Terminator: un exterminador modelo T-800 CSM-101 capturado y reprogramado por John Connor y enviado al pasado para proteger a Sarah Connor y a él mismo de joven.", vista_en: 3.years.ago }]) p "Creadas #{Pelicula.count} películas"
Lenguaje del código: Ruby (ruby)

Primero, borras todas las películas para tener un estado limpio y añades tres películas pasando un array al método create. El archivo de semillas usa ActiveSupport de Rails, para usar esos comandos X.ago tan útiles de Ruby para definir fechas.

Al final, hay un pequeño feedback sobre el total de películas creadas. ¡Vamos a ejecutarlo!

$ rails db:seed "Creadas 3 películas"
Lenguaje del código: Shell Session (shell)

Puedes ejecutar este comando tantas veces como necesites, gracias a la primera línea que contiene el destroy.

Para comprobarlas, puedes usar rails runner:

$ rails runner 'p Pelicula.pluck :titulo' ["Soul", "El Señor de los Anillos: La Comunidad del Anillo", "Terminator 2"]
Lenguaje del código: Shell Session (shell)

Usando una tarea personalizada de Rails para sembrar datos reales

Todas tus semillas son consideradas datos de desarrollo, no datos finales para uso en producción. Así que, ¡no siembres en producción de la manera que acabas de hacer! ¡Sobretodo porque el primer paso elimina todas las películas!

Para sembrar datos reales, es mejor crear una tarea personalizada de Rails. Vamos a generar una para añadir géneros:

rails g model Genero nombre ... rails db:migrate ... rails g task peliculas sembrar_generos
Lenguaje del código: Shell Session (shell)

Este comando crea un archivo rake de películas en el directorio lib/tasks conteniendo la tarea sembrar_generos.

Copia el código de abajo y pégalo en el archivo nuevo lib/tasks/movies.rake:

namespace :peliculas do desc "Siembra géneros" task sembrar_generos: :environment do Genero.create!([{ name: "Acción" }, { name: "Ciencia Ficción" }, { name: "Aventura" }]) p "Creados #{Genero.count} géneros" end end
Lenguaje del código: Ruby (ruby)

Ya aparece en la lista de comandos de Rails:

$ rails -T peliculas rake peliculas:sembrar_generos # Siembra géneros
Lenguaje del código: Shell Session (shell)

¡Hora de ejecutarla!

$ rails peliculas:sembrar_generos "Creados 3 géneros"
Lenguaje del código: Shell Session (shell)

Cargar semillas usando la consola

La consola es útil para jugar con tus datos. Vamos a abrirla:

$ rails c Loading development environment (Rails 6.1.3)
Lenguaje del código: Shell Session (shell)

¿Sabías que puedes cargar y acceder a tus semillas desde dentro? Prueba esto:

Rails.application.load_seed
Lenguaje del código: Ruby (ruby)

Jugando con datos usando la consola en modo sandbox

A veces necesitarás ejecutar comandos destructivos en datos reales en tu entorno de desarrollo o producción sin que afecte a los datos. Es como un modo seguro donde puedes hacer lo que quieras y volver a un estado anterior.

Este modo se llama sandbox, y puedes acceder a él con el comando rails c --sandbox

Entonces podrás hacer cosas como esta:

Esta técnica es útil para depurar una base de datos real, como cuando un usuario dice que actualizando su nombre de perfil se muestra un error raro. Podrías reproducir ese error directamente usando el modo sandbox sin que afecte a los datos reales.

Cargando más semillas usando Faker

Si necesitas, por ejemplo, 100 películas, puedes reemplazar tu archivo app/db/seeds.rb con esto:

Pelicula.destroy_all 100.times do |index| Pelicula.create!(titulo: "Título #{index}", director: "Director #{index}", sinopsis: "Sinopsis #{index}", vista_en: index.days.ago) end p "Creadas #{Pelicula.count} películas"
Lenguaje del código: Ruby (ruby)

Ahora ejecuta rails db:seed:

$ rails db:seed "Creadas 100 películas"
Lenguaje del código: Shell Session (shell)

Pero el resultado no parece nada realista:

$ rails runner 'p Pelicula.select(:titulo, :director, :sinopsis).last' #<Pelicula id: nil, titulo: "Título 99", director: "Director 99", sinopsis: "Sinopsis 99">
Lenguaje del código: Shell Session (shell)

Hora de usar Faker, una gema que genera valores aleatorios. Añádela en el grupo de desarrollo en tu Gemfile:

group :development, :test do # ... gem 'faker' end
Lenguaje del código: Ruby (ruby)

Ejecuta bundle install y reemplaza app/db/seeds.rb con esto:

Pelicula.destroy_all 100.times do |index| Pelicula.create!(titulo: Faker::Lorem.sentence(3, false, 0).chop, director: Faker::Name.name, sinopsis: Faker::Lorem.paragraph, vista_en: Faker::Time.between(4.months.ago, 1.week.ago)) end p "Creadas #{Pelicula.count} películas"
Lenguaje del código: Ruby (ruby)

Compruébalo otra vez:

$ rails db:seed "Creadas 100 películas" $ rails runner 'p Pelicula.select(:titulo, :director, :sinopsis, :vista_en).last' #<Pelicula id: nil, titulo: "Toy Story 2", director: "Michael Dickinson", sinopsis: "Modi esse et at eum deserunt harum qui itaque reru...", vista_en: "2020-11-18">
Lenguaje del código: Shell Session (shell)

¡Mucho mejor!

Conclusión

Sembrar la base de datos mientras desarrollas la aplicación es esencial, porque te dará la sensación de estar trabajando con datos reales.

También, conocer las herramientas disponibles para trabajar con semillas te hará sentir más cómodo y productivo, así que vale la pena invertir tiempo en aprenderlas.

Escrito por

David Morales

Ingeniero Técnico en Informática de Sistemas

Enseñando mis conocimientos en ingeniería del software de forma creativa.

¿Quieres el PDF Gratuito?

Consigue Las 10 Claves Ninja del Desarrollador, un PDF exclusivo para suscriptores de la Lista de Correo.

También serás notificado de futuros artículos y cursos económicos (en preparación) que te convertirán en un desarrollador ninja.

Ver información de privacidad

Escribe una respuesta

Por favor, rellena todos los campos.

Your email address will not be published.

Ver información de privacidad