Automatización de Inserción de Datos en Rails con db:seed
Objetivo
Una vez hemos construído el diseño base de nuestra base datos podemos crear un algoritmo para la inserción de registros a la base de datos de forma automática, a este proceso se le conoce como seeding (pronunciado [SI DIN] /ˈsiːdɪŋ/) de base de datos, el objetivo de esta clase, es crear esa estructura inicial de información que nos permita ingresar usuarios, tareas, categorías, participantes, haciendo uso de la tarea de rails rails db:seed que explicaremos más adelante.
rails db:seed
Rails, como habíamos visto tiene varios comandos que ejecutados desde la consola de comandos pueden generar o crear archivos y directorios que cumplen un propósito, para este caso, debemos introducir el concepto de tareas, las cuales son procesos preconfigurados que ejecutan una secuencia de instrucciones sobre algún área en particular, en las anteriores clases hemos interactuado con algunas de ellas, rails db:migrate es un buen ejemplo, esta tarea nos ayuda a ejecutar las migraciones pendientes de base datos; ahora, es el turno para rails db:seed tarea que usando el contenido de un archivo semilla ubicado en la dirección db/seeds.rb creará los registros que nosotros allí coloquemos.
Estructurando nuestro archivo semilla
Vamos a editar el contenido del archivo db/seeds.rb, primero eliminaremos todo su contenido, y empezaremos a agregar un conjunto de líneas de código
Creando usuarios
Dentro del archivo db/seeds.rb vamos a generar un arreglo de nombres
Luego vamos a iterar ese arreglo (recorrer elemento por elemento para hacer algo con cada uno)
['juan','andrea','leon','andres','natalia','camilo','rusbel','johan'].eachdo|name|
# la linea de creacion va aquí
end
Para finalmente, dentro del iterador usar el método create de la clase/modelo User, con el objetivo de crear un usuario, de esta forma, y recordando al modelo User, necesitamos los campos email y password para poder crear un nuevo usuario, asi que usaremos cada elemento del arreglo para formar un email utilizando interpolación de texto ”#{}” y usaremos la misma contraseña para todos 123456. Al final del iterador colocaremos un mensaje de texto mencionando que los usuarios han sido creados con éxito, todo este conjunto de pasos se verían de la siguiente forma en el archivo.
['juan','andrea','leon','andres','natalia','camilo','rusbel','johan'].eachdo|name|User.create email:"#{name}@platzi.com",password:'123456'
end
puts 'Users has been created'
Creando categorías
Similar al proceso de creación de usuarios también crearemos las categorías, usando un arreglo con el nombre de las mismas, y utilizando una descripción de prueba con la cadena ”--”
['desarrollo','mercadeo','conceptualización','ejercicios'].eachdo|name|Category.create name: name,description:'--'
end
puts 'Categories has been created'
Creando Tareas y Participantes
Este es el proceso más importante de nuestros datos semilla, vamos a usar una estructura basada en arreglos anidados para obtener toda la información que nuestra tarea y participantes necesitan, debo aclararte que esta estructura es una de las muchas formas que tu puedes encontrar para conseguir el mismo objetivo, es decir crear los registros automáticamente.
Una tarea necesita una categoría y un nombre, así que podemos usar las estrategias anteriores para crearla, sin embargo, para que las validaciones nos dejen seguir, necesitamos también asociar a la tarea un propietario y un conjunto de participantes.
El propietario es sencillo de relacionar, simplemente voy a tomar el usuario de nombre johan y haré una referencia hacia él con una variable local, Johan será el propietario de todas las tareas, para buscar y almacenar la referencia del propietario usaremos el método find_by y buscaremos una coincidencia por email dentro de los registros de usuarios previamente creados:
owner =User.find_by(email:'johan@platzi.com')
Para asociar la descripción y la categoría de la tarea podríamos usar un arreglo bidimensional, algo como esto:
[['conceptualización','Bienvenida']['conceptualización','¿Qué es ruby on rails y por qué usarlo?']['conceptualización','Entorno de desarrollo de RoR']['ejercicios','Instalación de Ruby, RoR en windows y Linux']]
No debes copiar estas líneas de los últimos dos bloques en el archivo, porque apenas estamos construyendo la idea de creación, y además sólo hemos resuelto parcialmente el problema; necesitamos una forma para pasar los participantes, teniendo en cuenta que cada participante tiene un Nombre y un Rol (responsable, o seguidor). Para conseguir esto vamos a usar otro arreglo más al mismo nivel de los elementos categoría y nombre del bloque anterior, sin embargo, para mejorar la visualización vamos a usar varias líneas para representar nuestros arreglos anidados y además para continuar con la explicación de una forma más sencilla vamos a usar una variable local de nombre base que almacenará nuestro arreglo contenedor de prueba.
base =[['conceptualización','Bienvenida ',['johan:1','leon:2','andrea:random']],['conceptualización','¿Qué es ruby on rails y por qué usarlo?',['johan:1','leon:2','andrea:random']],['conceptualización','Entorno de desarrollo de RoR',['johan:1','leon:2','andrea:random']],['ejercicios','Instalación de Ruby, RoR en windows y Linux',['johan:1','leon:2','andrea:random']],]
En el bloque anterior de código, podemos ver cómo hemos integrado un tercer elemento más, que resulta ser un nuevo arreglo, como lo vemos en el bloque de abajo; este arreglo resulta ser una convención que he elegido para referenciar un nombre de un usuario junto con su rol. Por ejemplo, johan:1 significa que el participante se llama Johan, y que su rol será 1, es decir responsable. Cuando el rol sea random vamos a usar un sistema de selección aleatoria de Ruby sobre alguno de los dos tipos de roles: 1 - responsable, 2 - seguidor
['johan:1','leon:2','andrea:random']
Vamos a ver cómo manipular este nuevo arreglo, asignemos una variable local llamada my_array al arreglo de arriba, y sigamos la siguiente secuencia:
my_array =['johan:1','leon:2','andrea:random']
vamos a tomar, cada uno de los elementos de ese arreglo y asignarlos a tres variables locales llamadas: first, second, third (podrías usar cualquier nombre en realidad). Este proceso se llama parallel assignment (pronunciado [paralel asainmen] /ˈperəˌlel əˈsaɪnmənt/) tenlo muy presente porque lo usaremos más adelante en el código final, el parallel assignment nos permite asignar de forma conmutada valores en secuencia del arreglo en el mismo orden en el que las variables serán definidas
first, second, third = my_array
Así, si evaluamos las tres variables usando la consola de rails, tendríamos lo siguiente
➜ ~ rc
> my_array =['johan:1','leon:2','andrea:random']> first, second, third = my_array
> first
#=>'johan:1'> second
#=>'leon:2'> third
#=>'andrea:random'
Te darás cuenta, que incluso no es necesaria la variable my_array y podrás hacer parallel assignment directamente con la declaración del arreglo, de esta forma
first, second, third =['johan:1','leon:2','andrea:random']
Una vez teniendo la referencia de cada uno de los tres participantes podemos usar el método split para obtener el nombre y rol, para el caso del primer elemento lo podríamos experimentar en la consola de rails (yendo a la raíz del proyecto en la consola) de la siguiente forma:
➜ organizador ~ rc
> first, second, third =['johan:1','leon:2','andrea:random']> first.split(‘:’)#=>["johan","1"]
Por lo que podemos usar parallel assignment tal que tengamos las variables name y raw_rol:
name, raw_role = first.split(‘:’)
Para el caso de la variable third que tiene el rol random usaremos el método sample de la clase Array para aleatoriamente seleccionar un elemento dentro del conjunto [1, 2], así que si quisiéramos iterar el arreglo de participantes incluyendo el término random debemos usar un if en su forma ternaria y el método sample de la siguiente forma:
Por último, para terminar nuestro experimento vamos a tomar el arreglo de prueba que habíamos definido antes llamado base, lo iteraremos para construir dentro de la misma iteración, un conjunto de participantes no persistidos en la base de datos haciendo uso del método new de la clase/modelo Participant, este conjunto se llamará participants
# la asignación de elementos del `each` es similar a la del parallel assignment, por eso
# podemos usar `category, description, participant_set` como elementos de la iteración
base.eachdo|category, description, participant_set|participants = participant_set.mapdo|participant|user_name, raw_role = participant.split(':')role = raw_role =='random'?[1,2].sample: raw_role
Participant.new(user:User.find_by(email:"#{user_name}@platzi.com"),role: role.to_i)
end
end
Teniendo los participantes previamente construidos, dentro de la misma iteración crearemos nuestras tareas usando un nombre consecutivo, la descripción del arreglo, la categoría del arreglo y una fecha de vencimiento de 15 días a partir de la creación de la tarea. Complementando el bloque de la siguiente manera:
base.eachdo|category, description, participant_set|participants = participant_set.mapdo|participant|user_name, raw_role = participant.split(':')role = raw_role =='random'?[1,2].sample: raw_role
Participant.new(user:User.find_by(email:"#{user_name}@platzi.com"),role: role.to_i)
end
# El nuevo código es el que está abajo
Task.create!(category:Category.find_by(name: category),name:"Tarea ##{Task.count + 1}",description: description,due_date:Date.today+15.days,owner: owner,participating_users: participants
)
end
puts 'Tasks has been created'
Una vez entendido todo el proceso, el código completo del archivo db:seed será el siguiente:
['juan','andrea','leon','andres','natalia','camilo','rusbel','johan'].eachdo|name|User.create email:"#{name}@platzi.com",password:'123456'
end
puts 'Users has been created'['desarrollo','mercadeo','conceptualización','ejercicios'].eachdo|name|Category.create name: name,description:'--'
end
puts 'Categories has been created'owner =User.find_by(email:'johan@platzi.com')[['conceptualización','Bienvenida ',['juan:1','leon:2','andrea:random']],['conceptualización','¿Qué es ruby on rails y por qué usarlo?',['juan:1','leon:2','andrea:random']],['conceptualización','Entorno de desarrollo de RoR',['juan:1','leon:2','andrea:random']],['ejercicios','Instalación de Ruby, RoR en windows y Linux',['juan:1','leon:2','andrea:random']],['conceptualización','Entender la web con rieles',['juan:1','leon:2','andrea:random']],['ejercicios','Crear una nueva aplicación RoR ¡Hola Rails!',['juan:1','leon:2','andrea:random']],['ejercicios','Manipular el patrón MVC',['juan:1','leon:2','andrea:random']],['conceptualización','¿Qué vamos a desarrollar?',['juan:1','leon:2','andrea:random']],['desarrollo','Crear la base de nuestra aplicación',['juan:1','leon:2','andrea:random']],['desarrollo','Los secretos de rails',['juan:1','leon:2','andrea:random']],['conceptualización','Assets y Layouts',['juan:1','leon:2','andrea:random']],['conceptualización','Diseñar el modelo de datos',['juan:1','leon:2','andrea:random']],['desarrollo','Agregar primer conjunto de scaffolds',['juan:1','leon:2','andrea:random']],['desarrollo','Cómo entender las migraciones',['juan:1','leon:2','andrea:random']],['desarrollo','Esteroides para tu desarrollo - HAML',['juan:1','leon:2','andrea:random']],['desarrollo','Esteroides para tu desarrollo - Simple Form',['juan:1','leon:2','andrea:random']],['desarrollo','Regenerando el primer conjunto de scaffolds',['juan:1','leon:2','andrea:random']],['desarrollo','Internacionalización de tu aplicación',['juan:1','leon:2','andrea:random']],['conceptualización','Esteroides para tu desarrollo - Debugging',['juan:1','leon:2','andrea:random']],['desarrollo','Agregar validaciones de modelo',['juan:1','leon:2','andrea:random']],['desarrollo','Añadiendo el concepto de usuario',['juan:1','leon:2','andrea:random']],['desarrollo','Añadir participantes a la tarea',['juan:1','leon:2','andrea:random']],['desarrollo','CanCanCan ¿puedes hacerlo?',['juan:1','leon:2','andrea:random']],['desarrollo','Callbacks en Rails',['juan:1','leon:2','andrea:random']],['desarrollo','Enviar email a los participantes',['juan:1','leon:2','andrea:random']],['desarrollo','Añadir comentarios vía AJAX',['juan:1','leon:2','andrea:random']],['desarrollo','Embellecer nuestra aplicación',['juan:1','leon:2','andrea:random']],['conceptualización','Desplegando a Heroku',['juan:1','leon:2','andrea:random']],['conceptualización','Conclusiones del curso',['juan:1','leon:2','andrea:random']],].eachdo|category, description, participant_set|participants = participant_set.mapdo|participant|user_name, raw_role = participant.split(':')role = raw_role =='random'?[1,2].sample: raw_role
Participant.new(user:User.find_by(email:"#{user_name}@platzi.com"),role: role.to_i)
end
Task.create!(category:Category.find_by(name: category),name:"Tarea ##{Task.count + 1}",description: description,due_date:Date.today+15.days,owner: owner,participating_users: participants
)
end
puts 'Tasks has been created'
Por favor necesito de sus ayuda compañeros y Profesor Johan Tique. Una vez culminado de agregar todo el codigo fui a la pagina y me sale este error:
Y obviamente apague el servidor y volvi a correrlo con rails s.
Luego pense que podria ser algo de la base, por eso mande a resetearla con rails db:reset y me sale esto que no entiendo:
Por favor necesito ayuda!!!!!!
Pudiste resolver tu duda? yo sigo atascado con ese error.
en el error dice que ingresaste particpants, fijate ese error
Listo!!
Cual fue el siguiente paso Jesus para que te saliera eso? Gracias
para cargar el archivo de seeds en la base de datos se usa el comando
$ rails db:seed
Solo cambiaria el texto del "puts" por "have" ya que esta en plural, por ejemplo
puts 'Users have been created'
Para que las tareas siempre se muestren ordenadas por el id, podemos agregar las siguiente linea de código a nuestro modelo Task:
default_scope { order(id: :asc) }
Buenas noches como se hace para llegar desde la consola rails a el archivo organizador como lo hace el profesor no he podido agradezco su colaboracion
Hola Sneider, si estoy entendiendo bien la pregunta, quieres usar la consola de Rails, si es asi, la consola de Rails sólo tiene sentido cuando estas en un proyecto, en este caso llamado organizador, dado que cuando accedes a ella estás practicamente cargando toda la aplicación con todo lo que eso implica.
Con esta introducción lo que debemos hacer es en una consola tipo bash o similar, ir al directorio donde está albergado el proyecto, en el inicio del curso hacemos ese tipo de navegación, una vez en el directorio del proyecto, que en este caso se llama organizador... debes escribir el comando rails console (estoy asumiendo que la instalación se hizo como están definidas las guías del curso)
Podrías darme un mejor contexto de tu configuración para ayudarte mejor, por ejemplo, sistema operativo, tipo de instalación, tipo de consola. Por otro lado, como te mencionaba arriba es posible que no este entendiendo bien tu pregunta, pero quedo muy atento
rails c
Buenas noches profesor, uso windows 10 mi preguntas es como hace usted para poner en su consola el organizador te lo mostrare en la imagen que te dejare mas abajo puesto que en la imagen tu accedes o sale esto.
➜ organizador ~ rc // A esto se refiere mi pregunta como hago en windows para llegar al organizador en mi consola
first, second, third = ['johan:1', 'leon:2', 'andrea:random']
first.split(‘:’)
#=> ["johan", "1"]
Hola, para windows 10 asumiré que tenemos la misma configuración de la clase 5 en donde tenemos una shell (basada en PowerShell bash), y RBENV como gestor de versiones de ruby y configurador de los binstubs
para acceder al código, en dicha clase lectura, mencionaba que podíamos usar nuestro disco de unidad C (o similar) haciendo uso del comando cd /mnt/c allí iríamos a la raíz de tu unidad C
luego de esto podemos crear nuestro directorio platzi (es como estar creando una carpeta vía interfaz gráfica, pero en lugar de esto, hacerlo a través de la consola)
En ese punto te sugería hacerlo con el comando mkdir -p coding/platzi ten en cuenta que estos comandos son extraidos de la consola Bash, no tienen nada que ver con Ruby o Ruby on Rails
bien, estando allí, podiamos dirijirnos a ese directorio recien creado usando el comando cd coding/platzi y desde allí empezar a crear nuestra aplicación Rails, por ejemplo rails new mi_app -T
esto automaticamente me creara un nuevo directorio llamado mi_app al que accederemos desde consola usando cd mi_app, estoy asumiendo que seguimos dentro del directorio platzi
una vez allí, ya podrás acceder a la consola de rails usando el comando rails console
yo en la clase estoy usando una consola diferente que enseño cómo instalar en la clase 4 está consola se llama zsh con un complementto llamado oh-my-zsh, la cual me permite tener una serie de herramientas para el desarrollo y además usar una serie de aliases como rc
Este es el código completo para quien lo necesite. Remarco que es 100% recomendable el leer todo el episodio
# db/seeds.rb# 1. Creación de usuarios['juan', 'andrea', 'leon', 'andres', 'natalia', 'camilo', 'rusbel', 'johan'].each do |name| User.create( email: "#{name}@platzi.com", password: '123456' ) end puts 'Users has been created' # 2. Creación de categorías ['desarrollo', 'mercadeo', 'conceptualización', 'ejercicios'].each do |category_name| Category.create( name: category_name, description: '--' ) end puts 'Categories has been created' # 3. Referencia al propietario de las tareas owner = User.find_by(email: 'johan@platzi.com') # 4. Definición de las tareas y sus participantes [ ['conceptualización', 'Bienvenida ', ['juan:1', 'leon:2', 'andrea:random']], ['conceptualización', '¿Qué es ruby on rails y por qué usarlo?', ['juan:1', 'leon:2', 'andrea:random']], ['conceptualización', 'Entorno de desarrollo de RoR', ['juan:1', 'leon:2', 'andrea:random']], ['ejercicios', 'Instalación de Ruby, RoR en windows y Linux', ['juan:1', 'leon:2', 'andrea:random']], ['conceptualización', 'Entender la web con rieles', ['juan:1', 'leon:2', 'andrea:random']], ['ejercicios', 'Crear una nueva aplicación RoR ¡Hola Rails!', ['juan:1', 'leon:2', 'andrea:random']], ['ejercicios', 'Manipular el patrón MVC', ['juan:1', 'leon:2', 'andrea:random']], ['conceptualización', '¿Qué vamos a desarrollar?', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Crear la base de nuestra aplicación', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Los secretos de rails', ['juan:1', 'leon:2', 'andrea:random']], ['conceptualización', 'Assets y Layouts', ['juan:1', 'leon:2', 'andrea:random']], ['conceptualización', 'Diseñar el modelo de datos', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Agregar primer conjunto de scaffolds', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Cómo entender las migraciones', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Esteroides para tu desarrollo - HAML', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Esteroides para tu desarrollo - Simple Form', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Regenerando el primer conjunto de scaffolds', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Internacionalización de tu aplicación', ['juan:1', 'leon:2', 'andrea:random']], ['conceptualización', 'Esteroides para tu desarrollo - Debugging', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Agregar validaciones de modelo', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Añadiendo el concepto de usuario', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Añadir participantes a la tarea', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'CanCanCan ¿puedes hacerlo?', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Callbacks en Rails', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Enviar email a los participantes', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Añadir comentarios vía AJAX', ['juan:1', 'leon:2', 'andrea:random']], ['desarrollo', 'Embellecer nuestra aplicación', ['juan:1', 'leon:2', 'andrea:random']], ['conceptualización', 'Desplegando a Heroku', ['juan:1', 'leon:2', 'andrea:random']], ['conceptualización', 'Conclusiones del curso', ['juan:1', 'leon:2', 'andrea:random']], ].each do |category_name, task_description, participant_set| # Construimos los participantes participants = participant_set.map do |participant| user_name, raw_role = participant.split(':') role = raw_role == 'random' ? [1, 2].sample : raw_role Participant.new( user: User.find_by(email: "#{user_name}@platzi.com"), role: role.to_i ) end # Creamos la tarea Task.create!( category: Category.find_by(name: category_name), name: "Tarea ##{Task.count + 1}", description: task_description, due_date: Date.today + 15.days, owner: owner, participating_users: participants ) end puts 'Tasks has been created'