En esta página:
Demo
En la parte anterior de este tutorial, creamos el controlador el cual contiene los métodos Crear, Leer, Actualizar y Eliminar.
Asimismo, creamos las vistas HTML, en donde más adelante agregaremos los elementos necesarios con Bootstrap. Por último, creamos las rutas, las cuales permiten cargar las vistas respectivas del sistema CRUD.
En esta penúltima y cuarta parte continuaremos con el tutorial Como Crear Un CRUD Con Ruby on Rails 7, vamos con ello.
Partes
Vamos a crear las vistas HTML con el framework Bootstrap, el cual instalamos en la parte 1 de este tutorial.
Vistas HTML (Bootstrap)
Cuando creamos el controlador, también creamos 4 archivos HTML: crear.html.erb, leer.html.erb, actualizar.html.erb y el archivo principal index.erb para listar todos los registros en una tabla.
Los 4 archivos HTML se encuentran en crud-rails-7 > app > views > postres:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/crud-rails-7 ├── /app ├── /assets ├── /channels ├── /controllers ├── /helpers ├── /javascript ├── /jobs ├── /mailers ├── /models ├── /views ├── /layouts ├── /postres // Archivos con las vistas HTML del sistema CRUD ├── actualizar.html.rb ├── crear.html.rb ├── index.html.rb ├── leer.html.rb ├── /bin ├── /config ├── /db ├── /lib ├── /log ├── /public ├── /storage ├── /test ├── /tmp ├── /vendor ├── .gitignore ├── .ruby-version ├── config.ru ├── Gemfile ├── Gemfile.lock ├── package.json ├── Rakefile ├── Gemfile.lock ├── README.md |
Pasemos a usar estos 4 archivos HTML para crear las interfaces correspondientes a cada vista del CRUD.
Ahora pasemos a crear las vistas para las tareas CRUD.
Crear (Create)
Para esta vista crearemos un formulario que servirá para insertar los datos a la base de datos, específicamente a la tabla postres.
Los campos que usaré en el formulario son: nombre, precio, stock, img y url (Este último es la url o slug del registro o postre).
Abrimos el archivo crear.html.erb y agregamos el siguiente formulario:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<form method="POST" action="/postres/insertar" accept-charset="UTF-8" role="form" id="crearpostre" name="crearpostre" enctype="multipart/form-data"> <!-- Protección CSRF --> <%= token_tag nil %> <div class="form-group mb-3"> <label for="nombre" class="negrita">Nombre:</label> <div> <input class="form-control" placeholder="Torta de Chocolate" name="nombre" type="text" id="nombre" onload="crearUrlAmigable(this.value);" onkeypress="crearUrlAmigable(this.value);" required> </div> </div> <div class="form-group mb-3"> <label for="precio" class="negrita">Precio:</label> <div> <input class="form-control" placeholder="4.50" name="precio" type="text" id="precio" required> </div> </div> <div class="form-group mb-3"> <label for="stock" class="negrita">Stock:</label> <div> <input class="form-control" placeholder="40" name="stock" type="text" id="stock" required> </div> </div> <div class="form-group mb-3"> <label for="img" class="negrita">Selecciona una imagen:</label> <div> <input class="form-control" type="file" name="img" id="img" required> </div> </div> <div class="form-group mb-3"> <label for="url" class="negrita">URL:</label> <div> <input type="text" class="form-control" name="url" id="url" readonly> </div> </div> <button type="submit" class="btn btn-info">Guardar</button> <a href="index" type="submit" class="btn btn-secondary">Cancelar</a> </form> |
En el código anterior, si ves el campo nombre llama a la función JavaScript crearUrlAmigable() en los eventos onload y onkeypress:
1 2 3 |
<input class="form-control" placeholder="Torta de Chocolate" name="nombre" type="text" id="nombre" onload="crearUrlAmigable(this.value);" onkeypress="crearUrlAmigable(this.value);" required> |
Esta función crearUrlAmigable() crea la url del registro en base al nombre que el usuario tipee en el campo nombre, el código JavaScript es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function crearUrlAmigable(str) { // Reemplaza los carácteres especiales | simbolos con un espacio str = str.replace(/[`~!@#$%^&*()_\-+=\[\]{};:'"\\|\/,.<>?\s]/g, ' ').toLowerCase(); // Corta los espacios al inicio y al final del string str = str.replace(/^\s+|\s+$/gm, ''); // Reemplaza el espacio con guión str = str.replace(/\s+/g, '-'); var input = document.getElementById('url'); input.value = str; } |
Para obtener el nombre de la imagen y almacenarlo en la base de datos, lo que hago es que el campo nimg llame a la función JavaScript cargarImagen() en el evento onchange:
1 2 3 |
<input class="form-control" type="file" name="nimg" id="nimg" onchange="cargarImagen()" required> |
El código de la función cargarImagen() es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function cargarImagen() { var name = document.getElementById('nimg'); //alert('Nombre: ' + name.files.item(0).name); //alert('Tamaño: ' + name.files.item(0).size); //alert('Tipo: ' + name.files.item(0).type) nas = name.files.item(0).name var ini = document.getElementById('img'); ini.value = nas; } |
Dentro del campo url se genera la url en base al nombre que el usuario tipee, esto se genera con la función JavaScript crearUrlAmigable(), asimismo he colocado el campo img que obtiene el nombre de la imagen con la función JavaScript cargarImagen():
1 2 3 4 5 6 7 8 9 |
<div class="form-group"> <label for="url" class="negrita">URL:</label> <div> <input type="text" class="form-control" name="url" id="url" readonly> <input type="text" class="form-control" name="img" id="img" readonly hidden> </div> </div> |
El campo url esta como solo lectura (readonly).
El campo img esta como solo lectura (readonly) y oculto (hidden).
Nuestra vista Crear se ve de la siguiente manera:
Ahora pasemos a crear la vista Leer.
Leer (Read)
Nuestra vista Leer, nos servirá para ver los detalles de un registro independiente.
Haremos uso de un foreach para llamar a los datos de un determinado registro por el id.
Agregamos el siguiente código al archivo leer.html.erb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<div align="left"> <% @postres.each do |postres| %> <h4><%= postres.nombre %> </h4> <strong>Stock:</strong><%= postres.stock %> <br> <br> <strong>Precio:</strong><%= postres.precio %> <br> <br> <strong>Creado:</strong><%= postres.created_at.strftime("%d/%m/%Y") %> <br> <br> <img src="/assets/img/<%= postres.img %>" class="img-fluid" title="<%= postres.nombre %>" alt="<%= postres.nombre %>"> <% end %> </div> |
Nuestra vista Leer se ve de la siguiente manera:
Pasemos a crear la vista Actualizar.
Actualizar (Update)
Esta vista la usaremos para colocar los datos de un determinado registro en un formulario y poder editarlos y enviar los cambios a la base de datos
Lo que haremos es usar un foreach para obtener y colocar los datos de un determinado registro (por id) en los campos correspondientes del formulario.
Abrimos el archivo actualizar.html.erb y le agregamos lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<div class="formulario" align="left"> <h4>Actualizar</h4> <% @postres.each do |postres| %> <form method="POST" action="/postres/editar/<%= postres.id %>" accept-charset="UTF-8" role="form" id="actualizarpostre" name="actualizarpostre" enctype="multipart/form-data"> <!-- Protección CSRF --> <%= token_tag nil %> <div class="form-group mb-3"> <label for="nombre" class="negrita">Nombre:</label> <input class="form-control" placeholder="Torta de Chocolate" name="nombre" type="text" id="nombre" onload="crearUrlAmigable(this.value);" onkeypress="crearUrlAmigable(this.value);" value="<%= postres.nombre %>" required> </div> <div class="form-group mb-3"> <label for="precio" class="negrita">Precio:</label> <input class="form-control" placeholder="4.50" name="precio" type="text" id="precio" value="<%= postres.precio %>" required> </div> <div class="form-group mb-3"> <label for="stock" class="negrita">Stock:</label> <input class="form-control" placeholder="40" name="stock" type="text" id="stock" value="<%= postres.stock %>" required> </div> <div class="form-group mb-3"> <label for="img" class="negrita">Selecciona una imagen:</label> <input class="form-control" type="file" name="img" id="img"> <br> <br>Imagen Actual: <br> <img src="/assets/img/<%= postres.img %>" class="img-fluid" title="<%= postres.nombre %>" alt="<%= postres.nombre %>"> </div> <div class="form-group mb-3"> <label for="url" class="negrita">URL:</label> <input type="text" class="form-control" name="url" id="url" value="<%= postres.url %>" readonly> </div> <button type="submit" class="btn btn-info">Guardar</button> <a href="index" type="submit" class="btn btn-secondary">Cancelar</a> </form> <% end %> </div> |
Nuestra vista Actualizar se ve de la siguiente manera:
Ahora pasemos a crear la vista Eliminar, que no es exactamente una vista, sino una funcionalidad en la vista principal del sistema CRUD.
Eliminar (Delete)
Para eliminar un registro no necesitaré una vista, ya que lo haremos con JavaScript en la vista principal en el archivo index.html.erb
Nuestra vista principal servirá para listar todos los registros en una tabla HTML y al lado derecho de cada registro colocaré 3 botones que digan Detalles, Editar y Eliminar:
Abrimos el archivo index.html.erb y agregamos lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<div class="table-responsive"> <!-- Mensajes --><% if flash[:notice] %> <div class="alert alert-success" role="alert" id="notice" class="notice"><%= flash[:notice] %> </div><% end %> <div align="left" class="btn_crear mb-3"> <a href="crear" type="button" class="btn btn-primary">Crear</a> </div> <table class="table table-striped table-hover"> <thead> <tr> <th width="35%">Nombre</th> <th>Precio</th> <th>Stock</th> <th>Imagen</th> <th>Acciones</th> </tr> </thead> <tbody><% @postres.each do |postres| %> <tr> <td class="v-align-middle"><%= postres.nombre %> </td> <td class="v-align-middle"><%= postres.precio %> </td> <td class="v-align-middle"><%= postres.stock %> </td> <td class="v-align-middle"> <img src="/assets/img/<%= postres.img %>" width="30" class="img-fluid" title="<%= postres.nombre %>" alt="<%= postres.nombre %>"> </td> <td class="v-align-middle"> <form method="POST" action="/postres/eliminar/<%= postres.id %>" accept-charset="UTF-8" class="form-horizontal" role="form" onsubmit="return ConfirmDelete()"> <!-- Protección CSRF --><%= token_tag nil %> <a href="/postres/leer/<%= postres.url %>" class="btn btn-dark">Detalles </a> <a href="/postres/actualizar/<%= postres.id %>" class="btn btn-primary">Editar </a> <button type="submit" class="btn btn-danger" onclick="return eliminarRegistro();">Eliminar</button> </form> </td> </tr><% end %> </tbody> </table> </div> |
La vista principal se ve así:
Si el usuario hace clic en el botón Eliminar, este llama a la función JavaScript eliminarRegistro(), el código de esta función es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 |
function eliminarRegistro() { var x = confirm("Estas seguro de Eliminar?"); if (x) return true; else return false; } |
Al llamar a la función eliminarRegistro() lanza una alerta preguntándole al usuario: Estas seguro de Eliminar? y si el usuario le de clic en el botón Aceptar, el sistema procede a borrar el registro y si hace clic en el botón Cancelar el sistema no hace nada:
Bien, hasta aquí ya tenemos creadas las vistas HTML con Bootstrap para el sistema CRUD.
Ten Paciencia, lo que quiero es que entiendas todo el proceso para Crear este Proyecto y no llenarte el capitulo de mucho contenido porque te puedes marear y no tendrás un óptimo aprendizaje.
Nota (s)
- Los Pasos y opciones mencionadas en este capitulo del tutorial pueden cambiar, esto no depende de nosotros, si no de los Desarrolladores que dan soporte a Ruby y Ruby on Rails, que suelen cambiar sus opciones de despliegue y configuración en futuras versiones.
- En la siguiente y última Parte, realizaremos ciertas configuraciones y otros detalles.
Síguenos en nuestras Redes Sociales para que no te pierdas nuestros próximos contenidos.