View
232
Download
4
Category
Preview:
Citation preview
Universidad de Costa Rica
Facultad de Ingeniería
Escuela de Ingeniería Eléctrica
IE – 0502 Proyecto Eléctrico
Sistema computarizado para el manejo de inventario de bodega.
Por:
Francisco José Zumbado Alvarez
Ciudad Universitaria Rodrigo Facio
Diciembre del 2008
Sistema computarizado para el manejo de inventario de bodega.
Por:
Francisco José Zumbado Alvarez
Sometido a la Escuela de Ingeniería Eléctrica
de la Facultad de Ingeniería
de la Universidad de Costa Rica
como requisito parcial para optar por el grado de:
BACHILLER EN INGENIERÍA ELÉCTRICA
Aprobado por el Tribunal:
_________________________________Ing. Andrés Díaz Soto
Profesor Guía
_________________________________ _________________________________ Ing. Roberto Rodríguez Rodríguez Ing. José Freddy Rojas Chavarría Profesor lector Profesor lector
DEDICATORIA
A Dios por todo lo que me da en la vida. A mi familia y amigos por todo el apoyo y
por ser una parte importante en mi vida.
RECONOCIMIENTOS
A los profesores que me ayudaron en la realización del proyecto,
así como a demás personas que hicieron esto posible.
INDICE GENERAL
ÍNDICE DE FIGURAS.................................................................................................................. viiÍNDICE DE CUADROS................................................................................................................ viiiNOMENCLATURA....................................................................................................................... ixRESUMEN...................................................................................................................................... xCAPÍTULO 1: Introducción......................................................................................................... 1
1.1 Justificación................................................................................................................... 11.2 Objetivo general............................................................................................................ 21.3 Objetivos específicos..................................................................................................... 2 1.4 Metodología................................................................................................................... 2
CAPÍTULO 2: Desarrollo Teórico................................................................................................ 42.1 Bases de Datos............................................................................................................... 4
2.1.1 Objetivo de una base de datos....................................................................... 4 2.1.2 Tipos de bases de datos.................................................................................. 52.1.3 Abstracción de datos..................................................................................... 6
2.2 Modelos de Datos.......................................................................................................... 72.2.1 Modelos lógicos basados en objetos.............................................................. 72.2.2 Modelos lógicos basados en registros........................................................... 82.2.3 Modelos físicos............................................................................................... 9
2.3 Sistemas Gestores de bases de datos........................................................................... 92.4 Lenguajes de definición de datos (DDL)..................................................................... 102.5 Lenguajes de manipulación de datos (DML)............................................................. 102.6 Administrador de base de datos.................................................................................. 102.7 Usuarios de base de datos............................................................................................ 112.8 Lenguaje relacional SQL............................................................................................. 11
2.8.1 Estructura básica.......................................................................................... 122.8.2 Tuplas duplicadas.......................................................................................... 132.8.3 Operaciones de conjuntos............................................................................. 132.8.4 Operadores agregados................................................................................... 132.8.5 HAVING.......................................................................................................... 142.8.6 Subconsultas................................................................................................... 142.8.7 Definición de datos......................................................................................... 142.8.8 Tipos de datos................................................................................................. 142.8.9 Índices............................................................................................................. 152.8.10 Vistas............................................................................................................. 152.8.11 Eliminación de tablas, índices y vistas....................................................... 162.8.12 Manipulación de datos................................................................................ 162.8.13 Normalización de bases de datos................................................................ 17
2.9 El lenguaje de programación Ruby............................................................................. 192.9.1 Filosofía del lenguaje..................................................................................... 202.9.2 Semántica....................................................................................................... 202.9.3 Sintaxis........................................................................................................... 202.9.4 Metaprogramación........................................................................................ 21
2.10 Modelo Vista Controlador......................................................................................... 212.10.1 Descripción del patrón................................................................................ 22
2.11 Ruby on Rails............................................................................................................... 222.11.1 Principios Fundamentales.......................................................................... 232.11.2 El Modelo Vista Controlador de Ruby on Rails......................................... 232.11.3 Soporte de bases de datos............................................................................. 24
CAPÍTULO 3: Estructura general del sistema de inventario de bodega.................................. 263.1 Estructura de la aplicación y aspectos generales........................................................ 263.2 Base de datos.................................................................................................................. 263.3 Modelo............................................................................................................................ 273.4 Controlador.................................................................................................................... 273.5 Vista................................................................................................................................
283.6 Archivos de configuración............................................................................................ 293.7 Otras carpetas............................................................................................................... 303.8 Plugins utilizados.......................................................................................................... 31
CAPÍTULO 4: Diseño de la base de datos.................................................................................. 334.1 Base de datos para activos de bodega......................................................................... 334.2 Base de datos para manejo de usuarios...................................................................... 35
CAPÍTULO 5: Modelo.................................................................................................................. 405.1 Modelos del sistema de activos..................................................................................... 405.2 Modelos del sistema de autenticación de usuarios.................................................... 42
CAPÍTULO 6: Controladores...................................................................................................... 446.1 Controladores de sistema de activos........................................................................... 446.2 Controladores de sistema de autenticación de usuarios........................................... 49
CAPÍTULO 7: Vistas.................................................................................................................... 557.1 Vistas del sistema de manejo de activos..................................................................... 557.2 Vistas del sistema de autenticación de usuarios........................................................ 617.3 Plantilla genérica para vistas ..................................................................................... 67
CAPÍTULO 8: Traducciones....................................................................................................... 71CAPÍTULO 9: Pruebas................................................................................................................ 74
9.1 Pruebas de validación................................................................................................. 749.2 Búsquedas.................................................................................................................... 76
CAPÍTULO 10: Conclusiones y recomendaciones..................................................................... 7810.1 Conclusiones................................................................................................................ 7810.2 Recomendaciones........................................................................................................ 79
BIBLIOGRAFÍA............................................................................................................................ 80
INDICE DE FIGURAS
Figura 1. Interrelación entre niveles de abstracción de datos..................................................... 7Figura 2. Diagrama ER para el sistema de manejo de activos.................................................. 35Figura 3. Vista para creación de activo......................................................................................... 57Figura 4. Vista para edición de activo........................................................................................... 59Figura 5. Vista de listado de activos............................................................................................... 61Figura 6. Vista de listado de usuarios............................................................................................ 63Figura 7. Vista de edición de contraseña....................................................................................... 64Figura 8. Vista de listado de roles asignados................................................................................ 65Figura 9. Vista de listado de roles no asignados............................................................................ 66Figura 10. Vista final del sistema para un usuario conectado..................................................... 69Figura 11. Vista final del sistema para un usuario desconectado................................................ 70Figura 12. Prueba de validación de placa existente...................................................................... 74Figura 13. Prueba de validación de número de serie en blanco.................................................. 75Figura 14. Prueba de validación de placa en blanco.................................................................... 75Figura 15. Prueba de validación de placa no numeral................................................................. 76Figura 16. Prueba de búsqueda de activo por número de serie. ................................................. 76Figura 17. Prueba de búsqueda de activo por placa.................................................................... 77
INDICE DE CUADROS
Cuadro 1. Activos en nivel de normalización 0............................................................................. 33Cuadro 2. Activos en nivel de normalización 1............................................................................. 33Cuadro 3. Activos en nivel de normalización 2............................................................................. 34Cuadro 4. Estados en nivel de normalización 2............................................................................ 34Cuadro 5. Marcas en nivel de normalización 2............................................................................. 34Cuadro 6. Modelos en nivel de normalización 3........................................................................... 34Cuadro 7. Marcas en nivel de normalización 3............................................................................. 35Cuadro 8. Tabla de roles................................................................................................................. 37Cuadro 9. Tabla de permisos.......................................................................................................... 37
NOMENCLATURA
ROR:Ruby on Rails.
CSS:Cascading Style Sheet. Hojas de estilo en cascada, formato utilizado para describir el formato de páginas escritas en HTML o XML. XML: Extensible Markup Language. Metalenguaje extensible de etiquetas utilizado en desarrollo web.
HTML: Hyper Text Markup Language. Lenguaje de marcado predominante en el desarrollo de páginas erb.
RTML: Real Time Markup Language. Lenguaje propietario de Yahoo utilizado para describir páginas web para la aplicaciopn Yahoo! Store Editor.
JavaScript: Lenguaje de programación interpretado utilizado principalmente en páginas web.
Framework:Estructura de soporte que permite desarrollar proyectos de software utilizando una metodología de desarrollo específica.
RESUMEN
Este proyecto tiene como objetivo desarrollar una aplicación que permita almacenar y
manejar la información de los equipos existentes en el inventario de la bodega de la escuela de
Ingeniería Eléctrica de la Universidad de Costa Rica.
Se utilizó el gestor de base de datos PostgreSQL debido a su buena reputación y estabilidad
en el manejo de las bases de datos.
Para desarrollar la aplicación web se utilizó el lenguaje Ruby mediante un framework de
desarrollo denominado Ruby on Rails.
La estructura de la aplicación como de cualquier aplicación de Ruby on Rails, sigue el
paradigma Modelovistacontrolador. Este permite separar la aplicación en un modelo que realiza la
comunicación con la base de datos, una vista que maneja la parte visible para el usuario, es decir las
páginas web propiamente y un controlador encargado de interpretar y ejecutar las acciones
realizadas por el usuario y permite enlazar el modelo y las vistas de la aplicación.
La aplicación se dividió en una base de datos para manejo de los activos de bodega, en la
cual se almacenan los diferentes activos clasificados por marca, modelo, estado y con su respectivo
número de placa y serial, y una base de datos para el almacenamiento de la información de los
usuarios y las sesiones de estos.
De esta manera se añadió a la aplicación un sistema de autenticación de usuarios con
diferentes permisos para estos, según sean usuarios normales que únicamente puedan consultar la
información o usuarios administradores que pueden modificar la información.
Finalmente la aplicación desarrollada cumple con los objetivos planteados y se determinó
que es adecuada para cumplir la función deseada de almacenar la información de el inventario de la
bodega de la escuela al mismo tiempo que permite a los usuarios consultar y modificar información
de manera remota a través de Internet.
CAPÍTULO 1: Introducción.
1.1 Justificación.
En la actualidad vivimos en un mundo en el cual la eficiencia es un factor determinante en
todos los campos, y la búsqueda de esta ha llevado al desarrollo tecnológico con equipos que son
capaces de realizar tareas que antes debían realizarse completamente por personas, lo cual
conllevaba a muchos errores humanos y que además requerían de mucho tiempo para llevarse a
cabo.
El desarrollo de la computación ha permitido ampliar de gran forma las funcionalidades que
se le pueden dar a los avances tecnológicos, ya que ha permitido un procesamiento rápido y eficaz
de la información. El desarrollo de bases de datos para llevar registros informáticos es una de las
cosas que más ha contribuido en el manejo de la información, lo que las ha llevado a expandirse y
popularizarse en muchos campos, convirtiéndolas en una herramienta indispensable a la hora de
competir.
El almacenamiento de la información ha sido un aspecto muy importante, sin embargo este
almacenamiento no serviría de mucho si no se tuviera un adecuado acceso a la información. Las
redes de computadoras han sido fundamentales en este aspecto, permitiendo a usuarios acceder a
información en otro lado del mundo desde una computadora, a través de la Internet o de redes
privadas de información.
Este proyecto pretende utilizar estas herramientas que nos presenta la tecnología actual para
crear un sistema de almacenamiento computarizado para el inventario de la bodega de la Escuela de
Ingeniería Eléctrica de la Universidad de Costa Rica, mediante una base de datos manejada por
medio de una interfaz web, que permita a los funcionarios de la bodega llevar un registro más
adecuado de los equipos y materiales presentes en la bodega y que a la vez permita a los estudiantes
y profesores acceder a este inventario de forma remota para comprobar la existencia y
1
disponibilidad de materiales.
1.2 Objetivo general.
● Crear un sistema computarizado de base de datos que permita almacenar, consultar y
modificar el inventario de la bodega de la Escuela de Ingeniería Eléctrica de la Universidad
de Costa Rica, permitiendo al usuario un manejo simple mediante una interfaz web.
1.3 Objetivos específicos.
● Diseñar e implementar una base de datos que permita describir de manera óptima los activos
de la bodega de la Escuela de Ingeniería Eléctrica de la Universidad de Costa Rica.
● Seleccionar el gestor de base de datos, lenguajes de programación y herramientas que se
utilizarán para el desarrollo de la aplicación, utilizando criterios tales como rendimiento,
flexibilidad y seguridad, entre otros.
● Desarrollar una aplicación web que permita hacer consultas y administrar la base de datos.
● Crear un sistema de control de acceso para restringir el acceso a algunas funciones de la
base de datos asignando ciertos permisos a los usuarios.
1.4 Metodología.
● Se investiga sobre bases de datos de licencia libre y los diferentes gestores para determinar el
gestor que más se adecúa a las necesidades y requerimientos del proyecto.
● Se investiga sobre la teoría de bases de datos para utilizarla en el diseño de la base de datos a
construir.
● Se realiza una entrevista con el encargado de la bodega para recolectar información sobre los
diferentes aspectos que debe considerar la base de datos para el inventario.
● Se realiza una entrevista con el profesor tutor Jose Freddy Rojas para obtener una guía en el
diseño de la base de datos.
● Se diseña la base de datos, tomando en cuenta la información recopilada y utilizando
2
técnicas de diseño adecuadas.
● Se investiga sobre los lenguajes más adecuados que permitan crear una interfaz web para la
base de datos diseñada, para escoger el lenguaje más conveniente.
● Se investiga sobre el lenguaje escogido y sus diferentes herramientas que permitan el
desarrollo del proyecto.
● Se desarrolla una interfaz web para la base de datos, que permita al usuario interactuar con
esta de manera.
● Se realizan pruebas a la aplicación para detectar y corregir fallas en el sistema y garantizar el
buen funcionamiento.
● A lo largo de todo el proyecto se desarrolla la documentación escrita de este.
3
CAPÍTULO 2: Desarrollo Teórico.
2.1 Bases de Datos [1][2].
Las bases de datos o bancos de datos son conjuntos de datos que forman parte de un mismo
contexto y son almacenados de una forma ordenada para su utilización posterior.
Una biblioteca es un ejemplo de base de datos, donde la mayoría de los datos son
documentos impresos y textos.
El desarrollo tecnológico y en especial de la computación ha contribuido a desarrollar
nuevas y más eficientes formas de almacenar bases de datos.
Los sistemas de bases de datos están diseñados para poder almacenar grandes cantidades de
datos, lo que implica la creación de estructuras adecuadas para almacenar la información así como
así como de mecanismos para la gestión de esta.
Otro punto importante en las bases de datos es que deben ser los suficientemente seguras
para garantizar el almacenamiento confiable de datos y no permitir manipulación por parte de
personas no autorizadas.
2.1.1 Objetivo de una base de datos.
Los sistemas de bases de datos son creados para evitar diversos problemas en el
almacenamiento de datos como los siguientes:
● Redundancia e inconsistencia de los datos: La redundancia puede aumentar el costo de
almacenamiento y acceso, además se puede presentar el caso de que diferentes copias de los
datos no concuerden por lo que se presenta una inconsistencia en los datos, por ejemplo si
para un cliente de un banco se presentan varias direcciones de domicilio.
● Dificultad de acceso a los datos: Cuando la cantidad de datos es considerable, se puede
querer encontrar los datos que cumplan ciertas características, lo cual se puede complicar si
no se utilizan métodos adecuados ya que sería necesario filtrar esta información de manera
4
manual o bien crear una aplicación nueva que haga este trabajo.
● Aislamiento de datos: La diferencia de formatos y de lugares de almacenamiento puede
provocar que sea difícil obtener todos los datos necesarios.
● Anomalías del acceso concurrente: En sistemas de almacenamiento de datos que permiten
a varios usuarios acceder y actualizar la información al mismo tiempo, pueden ocurrir
anomalías a la hora de hacer esta actualización de los datos, por ejemplo si se modifica un
dato al mismo tiempo por 2 usuarios, el resultado final puede ser incorrecto.
● Problemas de Seguridad: El acceso a la información debe ser restringido a ciertos usuarios
de manera que otros no autorizados sean bloqueados y se de un acceso seguro a la
información.
● Problemas de Integridad: El sistema de almacenamiento de datos debe ser capaz de evitar
que algunos datos obtengan ciertos valores que se considerarían erróneos, para de esta
manera lograr mantener la integridad de los datos.
Todos estos problemas han llevado a la creación de sistemas gestores de bases de datos para
evitar que se presenten dichos problemas, y así lograr un almacenamiento de los datos más
eficiente.
2.1.2 Tipos de bases de datos.
Las bases de datos se pueden clasificar de diferentes formas:
Según la variabilidad de los datos:
● Estáticas: Son bases de datos de solo lectura que puede utilizarse para almacenar datos
históricos donde los datos no deben variar en el tiempo.
● Dinámicas: En estas bases de datos la información almacenada es modificada a través del
tiempo, de manera que se le agregan nuevos datos y otros son actualizados, además por
5
supuesto de operaciones de consulta.
Según su contenido:
● Bibliográficas: Contienen únicamente los datos para la localización de la fuente primaria.
Por ejemplo la base de datos de una biblioteca que contiene los datos de los textos y en que
sección se puede localizar pero no contiene el documento en sí.
● De texto completo: Almacenan fuentes primarias en su totalidad por ejemplo todo
contenido de diferentes ediciones de libros y revistas.
● Directorios: Un ejemplo son las guías telefónicas.
● De información biológica: Almacenan información de datos biológicos como secuencias
de nucleótidos y proteínas.
2.1.3 Abstracción de datos.
La abstracción de datos se presenta en 3 niveles distintos:
● Nivel físico: Este nivel es el más bajo y describe la forma en que los datos son almacenados
físicamente.
● Nivel conceptual: El nivel conceptual describe cuales datos van a ser almacenados
realmente y cual es la relación entre estos datos. En este nivel trabaja el administrador de la
base de datos que es el que decide la información que se almacenará.
● Nivel de Visión: El nivel de visión muestra solo una parte de la base de datos que puede ser
importante según el usuario que acceda a los datos. Desde este nivel pueden haber varios
puntos de vista dependiendo del usuario.
La siguiente figura nos muestra la interrelación entre estos niveles de abstracción:
6
Figura 1. Interrelación entre niveles de abstracción de datos.
2.2 Modelos de Datos [1].Un modelo de datos es un grupo de herramientas conceptuales que se utilizan para describir
los datos, las relaciones entre ellos, la semántica y las restricciones de consistencia. Se dividen en:
modelos lógicos basados en objetos, modelos lógicos basados en registros y modelos físicos.
2.2.1 Modelos lógicos basados en objetos.
Los modelos lógicos basados en objetos se utilizan para describir datos en el nivel
conceptual y el nivel de visión. Estos modelos permiten una estructuración flexible, además que
permiten especificar restricciones de los datos explícitamente.
Existen varios modelos de este tipo, sin embargo los más representativos son el modelo
entidadrelación y el modelo orientado a objetos.
El modelo entidadrelación:
En este modelo se definen entidades que son objetos que se distinguen de otros objetos por
ciertos atributos específicos que poseen. Además se describen las relaciones que presentan
diferentes entidades.
El modelo presenta además las restricciones a las que se deben ajustar la base de datos como
por ejemplo la cantidad de entidades a la que se puede ajustar otra entidad por medio de un conjunto
de relación.
7
Vista 1 Vista 2 Vista n
Nivel Conceptual
Nivel físico
La estructura de un modelo entidad relación se puede describir gráficamente por medio de
diagramas ER, los cuales presentan las diferente entidades y su relación entre ellas así como los
atributos de cada entidad.
El modelo orientado a objetos:
Este modelo se basa en una colección de objetos los cuales contienen valores almacenados
en variables. Estos valores se consideran a la vez objetos, por lo que se tienen objetos que contienen
otros objetos que operan sobre el objeto. Además el objeto se componen de códigos que se
denominan métodos y que operan también sobre el objeto.
La diferencia con el modelo entidadrelación es que en el modelo orientado a objetos cada
objeto posee su propia identidad sin importar los valores que contiene.
2.2.2 Modelos lógicos basados en registros.
Los modelos basados en registros describen datos en el nivel conceptual y físico. Estos
modelos se utilizan para especificar la estructura lógica de la base de datos, además de proporcionar
una descripción a un nivel más alto de la implementación.
Este modelo trabaja con registros fijos en el nivel físico, los cuales poseen un tipo fijo y una
longitud también fija. Estos modelos no poseen mecanismos para la representación directa del
código en la base de datos, sino que se apoyan en otros lenguajes separados que se asocian al
modelo para realizar las consultas y actualizaciones a la base de datos.
Los modelos más importantes basados en registros son el modelo relacional, el de red y el
modelo jerárquico. El primero de ellos es el más aceptado.
Modelo relacional: Este modelo presenta los datos e la relación entre ellos en una colección
de tablas. Cada tabla presenta un número de columnas determinado.
Modelo de red: En el modelo de red los datos se presentan mediante colecciones de
registros, y las relaciones se presentan mediante enlaces, que se pueden ver como punteros.
8
Modelo jerárquico: El modelo jerárquico es parecido al modelo de red pues los datos y sus
relaciones son presentados en registros y enlaces. La diferencia es que en este modelo los
registros se ordenan como colecciones de árboles.
La diferencia entre los modelos relacionales y los de red y jerárquicos radica en que en los
dos últimos se utilizan punteros o enlaces, mientras que en el relacional se conectan estos registros
mediante los valores que contienen.
2.2.3 Modelos físicos.
Estos modelos se utilizan para describir los datos en el nivel más bajo. Los más conocidos
son el modelo unificador y el de memoria de los elementos.
2.3 Sistemas Gestores de bases de datos [1][3].
Un sistema gestor de base de datos (SGBD), es una aplicación de software específica que
está dedicada a funcionar como una interfaz entre la base de datos, el usuario y los programas que
utilizan dicha información.
Estos permiten a los usuarios acceder modificar los archivos que contienen la información,
presentando esta información al usuario a través de diversos niveles de abstracción de manera que la
interacción con el sistema sea lo más simple posible para el usuario.
El propósito final de los SGBDs es el de manejar de forma sencilla y ordenada conjuntos de
datos relevantes para brindar un buen manejo de estos.
Un SGBD cumple las siguientes funciones:
● Interactuar con el gestor de archivos: Los datos se almacenan en el disco duro utilizando el
sistema de archivos propio del sistema operativo utilizado. El SGBD es el encarado de
transformar las sentencias de almacenamiento de los datos al formato propio del sistema de
archivos de bajo nivel.
● Implantación de la integridad: El SGBD se encarga de hacer cumplir las restricciones que
9
pueden tener ciertos datos. El administrador de la base de datos es el encargado de
especificar estas restricciones.
● Implantación de la seguridad: Se deben cumplir los requisitos de seguridad de la base de
datos para evitar accesos no autorizados a esta por parte de usuarios restringidos.
● Copia de seguridad y recuperación: El SGBD debe detectar fallos en la base de datos como
problemas con el disco de almacenamiento y debe ser capaz de crear copias de seguridad
para una vez que se presente un fallo poder recuperar dicha información.
● Control de concurrencia: Se debe controlar la interacción de varios usuarios que actualizan
la base de datos simultáneamente, para que se conserve la consistencia de los datos.
2.4 Lenguajes de definición de datos (DDL) [1].
Un lenguaje de definición de datos especifica el esquema de una base de datos por medio de
un conjunto de sentencias. El resultado de la compilación de estas sentencias es un conjunto de
tablas almacenadas en un archivo llamado “diccionario de datos”.
2.5 Lenguajes de manipulación de datos (DML) [1].
Un lenguaje de manipulación de datos permite a los usuarios acceder y manipular los datos
según su organización.
Pueden ser de dos tipos:
● Procedimentales: Estos requieren que es usuario especifique los datos que son necesitados y
de que manera obtenerlos.
● No procedimentales: El usuario debe especificar los datos necesitados pero no como
obtenerlos.
2.6 Administrador de base de datos [1].
Un administrador de bases de datos es la persona que tiene el control central de los datos y
10
de los programas que acceden a la base de datos o en inglés database administrator (DBA).
Los administradores de bases de datos tienen varias funciones entre las que se encuentran:
● Definir el esquema.
● Definir la estructura de almacenamiento y el método de acceso.
● Modificar el esquema y la organización física.
● Conceder autorización de acceso a los usuarios.
● Especificar las restricciones de integridad de los datos.
2.7 Usuarios de base de datos [1].
Existen cuatro tipos distintos de usuarios de base de datos que se diferencian por la forma en
que interactúan con el sistema:
● Programadores de aplicaciones: Son usuarios que crean aplicaciones para interactuar con
el sistema por medio de sentencias DML incorporadas en un lenguaje principal.
● Usuarios sofisticados: Son usuarios que interaccionan con el sistema sin escribir
programas. Únicamente hacen sus consultas en el lenguaje de consultas de la base de datos.
● Usuarios especializados: Son usuarios que escriben aplicaciones de bases de datos
especializadas que no encajan en el marco tradicional de procesamiento de datos.
● Usuarios ingenuos: Son usuarios que interactúan con el sistema utilizando los programas de
aplicación creados. Como un usuario de un cajero automático.
2.8 Lenguaje relacional SQL [1] [8].
El lenguaje SQL fue desarrollado originalmente por la empresa IBM al inicio de la decada
de los setenta. Su nombre significa lenguaje de consulta estructurado, del inglés Structured Query
Language.
Este lenguaje se ha establecido como el lenguaje relacional de base de datos estándar.
Posee varias partes:
11
● Lenguaje de definición de datos (DDL): Proporciona órdenes que definen los esquemas de
relación. Además eliminan relaciones, crean índices y modifican los esquemas.
● Lenguaje De manipulación de datos (DML): El SQL incluye un sistema de consultas basado
en álgebra relacional y cálculo relacional de tuplas. Además se pueden insertar, eliminar y
modificar tuplas en la base de datos.
● Definición de vistas: Se incluyen órdenes para definir vistas.
● Autorización: Se pueden definir permisos de acceso a diferentes relaciones y vistas.
● Integridad: Se incluyen órdenes para especificar restricciones de integridad complejas.
● Control de transacciones: Incluye órdenes para especificar el inicio y el final de las
transacciones. Además algunas implementaciones permiten bloqueo de datos para control de
concurrencia.
2.8.1 Estructura básica.
Una expresión SQL consta de tres cláusulas básicas: select, from y where.
● Select: Esta operación se usa para listar los atributos que se desean en el resultado de la
consulta.
● From: Esta cláusula lista las relaciones que se van a examinar en la ecaluación de la
expresión.
● Where: Implica los atributos de las relaciones que se especificaron con la cláusula from.
Una consulta típica en SQL presenta la siguiente estructura:
select A1, A2, ..., An
from r1, r2, ...,rm
where P
Donde los Ai representan atributos mientras que los ir representan relaciones. Además P es
un predicado.
Si se omite la cláusula where se da por un hecho que el predicado P es verdadero. Para
12
indicar todos los atributos se puede sustituir los Ai por un asterisco (*), esto seleccionará todos los
atributos de las relaciones ri .
2.8.2 Tuplas duplicadas.
El lenguaje SQL así como casi todos los lenguajes de consulta comerciales permiten
duplicados en las relaciones. Hay veces que queremos eliminar estos duplicados, para esto se utiliza
el la palabra distinct despúes de la frase select, de la siguiente forma:
select distinct Xfrom Y
De manera contraria se utiliza la palabra all para evitar que se eliminen los duplicados.
select all Xfrom Y
2.8.3 Operaciones de conjuntos.
Las operaciones de conjuntos unión, intersección y diferencia son incluidas por el lenguaje
SQL.
Para la operación de unión se utiliza la sentencia union, para la operación de intersección se
utiliza intersect, mientras que para la operación de diferencia se utiliza la palabra minus.
La operación union elimina las tuplas duplicadas automáticamente. Para mostrar los
duplicados debemos escribir union all.
La operación union es parte del estándar SQL, sin embargo varios productos no las
soportan. Mientras tanto las operaciones intersect y minus no se incluyen en el estándar.
2.8.4 Operadores agregados.
SQL presenta operadores agregados que utilizan como argumento un atributo. El valor del
operador agregado se calcula sobre todos los elementos de la columna especificada o de ser
especificados grupos se calculará sobre los valores de cada grupo.
13
● AVG: Calcula el costo promedio.
● COUNT: Hace una cuenta de los artículos que pertenecen a la tabla.
● SUM: Calcula la suma de todos los valores.
● MIN: Calcula el valor mínimo.
● MAX: Calcula el valor máximo.
2.8.5 HAVING.
La cláusula having es similar a la cláusula where, es utilizada para considerar solo grupos
que cumplan un requisito específico. Esta cláusula utiliza expresiones que contengan funciones
agregadas. Toda función que involucre expresiones con funciones agregadas debe ir en esta
cláusula.
2.8.6 Subconsultas.
Las cláusulas having y where permiten el uso de subconsultas en cualquier lugar en donde se
espere un valor. El valor de la subconsulta debe derivar de la subconsulta previa, esta propiedad
amplia el poder expresivo de SQL.
Una subconsulta puede ser de la siguiente forma:
select Xfrom Ywhere Z > (select Z
from Y where W= 'frase')
2.8.7 Definición de datos.
SQL posee varias sentencias utilizadas para definir datos. Para definir relaciones se usa el
comando create table que crea una tabla con los atribuutos especificados.
La sintaxis de este comando es la siguiente:
create table nombre de la tabla(atributo 1, tipo del atributo 1[,atributo 2, tipo del atributo 2][,...]);
14
2.8.8 Tipos de datos.
SQL soporta varios tipos de datos. Los tipos más importantes y utilizados se muestran a
continuación:
● INTEGER: Es un entero binario de 31 bits de precisión con signo de palabra completa.
● SMALLINT: Un entero binario con signo de media palabra de 15 bits de precisión.
● DECIMAL (p[,q]): Es un número decimal con signo que presenta p digitos de precisión y
además contiene q digitos a la derecha del punto decimal.
● FLOAT: Número de doble palabra con signo y con coma flotante.
● CHAR(n): Es una cadena de caracteres con una longitud fija de n caracteres.
● VARCHAR (n): Es una cadena de caracteres con una longitud variable de un valor máximo
de n caracteres.
2.8.9 Índices.
Los índices nos permiten realizar de una forma más rápida el acceso a una relación, se puede
comparar con un índice de un libro que nos permite encontrar de manera más rápida la ubicación de
la información que necesitamos.
El índice evita que el sistema de archivos lea toda la tabla para localizar la información
deseada, y permite al sistema de base de datos chequear el valor del índice primero para ver si este
le permite encontrar de forma más rápida la información.
Es recomendado crear índices en las tablas para hacer más eficiente el acceso a la
información. Para crear un índice se utiliza el comando create index. La sintaxis utilizada es la
siguiente:
create index nombre_del_indiceon nombre_de_la _tabla (nombre_del_atributo);
El único cambio que puede percibir un usuario con la utilización de índices es el incremento
15
en la velocidad a la hora de buscar información.
2.8.10 Vistas.
Una vista es una tabla virtual, es decir una tabla que no existe físicamente en la base de
datos pero que el usuario la puede ver como si existiese.
La vista no tiene datos propios almacenados, sino que el sistema guarda la definición de la
vista que permite saber cuales son las tablas base que presentan la información que la vista necesita.
El comando utilizado para crear vistas es create vie. La sintaxis que se utiliza es:
create view nombre_de_la _vistaas sentencia_select
Sentecia _select se refiere a una instrucción select que permite adquirir la información para
crear la tabla de la vista.
2.8.11 Eliminación de tablas, índices y vistas.
Para eliminar tablas se utiliza la instrucción drop table, con ls siguiente sintaxis:
drop table nombre_de_la_tabla
Para la eliminación de indices se utiliza el comando drop index, la sintaxis es la siguiente:
drop index nombre_del_índice
Para eliminar vistas se utiliza el comando drop view, con la siguiente sintaxis:
drop view nombre_de_la_vista
2.8.12 Manipulación de datos.
Existen comandos para manipulación de datos que permiten insertar, actualizar y borrar los
datos en cada tabla.
Para insertar tuplas a las tablas se utiliza el comando insert into, que presenta la siguiente
sintaxis:
insert into nombre_de_la_tabla (nombre_atributo_1
16
[, nombre_atributo_2] [,...])values (valor_atributo_1
[, valor_atributo_2][, ...]);
Para borrar una tupla se utiliza el comando delete from, con la siguiente sintaxis:
delete from nombre_de_la_tablawhere condición;
También se pueden realizar cambios en un valor anteriormente ingresado, para lo cual se
utiliza el comando update, que presenta la siguiente sintaxis:
update nombre_de_la_tablaset nombre_atributo_1 = valor_1 [,...[,nombre_atributo_k = valor_k]]where condición;
2.8.13 Normalización de bases de datos [4].
La normalización de bases de datos es un proceso utilizado en el diseño de bases de datos
relacionales, mediante el cual se pueden evitar ciertos problemas en el manejo de los datos.
En la normalización se transforman los datos en estructuras más pequeñas de manera que
sean más simples, más estables y más fáciles de mantener. Además hace más fáciles de entender las
estructuras de datos para las personas .
Otra de sus ventajas consiste en que se reduce el espacio de almacenamiento porque se
evitan datos duplicados.
La normalización permite básicamente evitar redundancia en los datos almacenados, además
de problemas en la actualización de estos datos. Permite de esta forma garantizar la integridad de
los datos.
En el modelo relacional de bases de datos, las relaciones se suelen ver como tablas, siempre
y cuando cumplan ciertos requisitos como que todas las columnas deben tener un nombre único.
17
Las filas de la tabla o “tuplas” no pueden estar repetidas, es decir, no se permiten datos duplicados.
Además en una columna todos los datos deben ser del mismo tipo.
Formas normales:
Las formas normales son los diferentes niveles de normalización que se pueden alcanzar al
realizar un diseño de una base de datos.
Existen 5 formas normales, sin embargo las primeras 3 formas son suficientes para las
necesidades de la mayoría de bases de datos . Inclusive se considera en algunos casos inadecuado
llevar una base de datos a un nivel mayor al necesario ya que puede aumentar el nivel de
complejidad de esta innecesariamente.
Forma normal 1 (1NF):
En esta forma se establece que se deben eliminar todos los grupos repetitivos en las tablas.
Además se debe crear una tabla separada para los tipos de datos relacionados.
Por último se establece que cada tabla debe tener una clave primaria para identificar a sus
datos, esta clave primaria debe ser única para cada elemento de la tabla.
Forma normal 2 (2NF):
La segunda forma normal establece que las tablas que poseen grupos de datos que se aplican
a varios elementos a la vez se deben crear tablas separadas para dichos datos y se debe relacionar
dichas tablas mediante claves externas.
Forma normal 3 (3NF):
El tercer nivel de normalización tienen como objetivo evitar que existan datos duplicados o
errores en estos, por lo cual se debe ubicar en tablas separadas los elementos que no dependan de la
clave, es decir los elementos en la tabla que no sean exclusivos de el elemento de la tabla que se
identifica con el identificador de la tabla.
El tercer nivel de de normalización implica que las tablas pueden crecer todo lo que quieran
18
sin duplicación ni corrupción de datos. Este nivel de normalización se dice suficiente para la
mayoría de las aplicaciones, ya que puede manejar los datos obtenidos en su totalidad de una
manera fácil.
Forma normal 4 (4NF):
En casos específicos en los que se tiene una relación de “variosconvarios” es decir, que un
elemento de la tabla A tenga varios elementos de la tabla B, y que al mismo tiempo un elemento de
la tabla B tenga varios elementos de la tabla A, se necesita un nivel de formalización 4.
Este nivel de formalización indica que cuando existen relaciones de “variosconvarios”, las
entidades independientes no se pueden almacenar en la misma tabla.
Forma normal 5 (5NF):
Este nivel de normalización se aplica algunas veces, sin embargo en la mayoría de los casos
no es necesario para obtener una mejor funcionalidad en nuestra aplicación.
El principio de esta dice que se puede reconstruir la tabla original desde las tablas
resultantes en las que fue separada dicha tabla.
El aplicar esta regla permite asegurar que no se ha creado ninguna entrada extraña en las
tablas, y que la estructura de tablas creada es del tamaño justo. Sin embargo no es necesaria a
menos que se este trabajando con una estructura de datos demasiado extensa.
2.9 El lenguaje de programación Ruby [5] [7].
Ruby es un lenguaje de programación orientado a objetos, interpretado y multiplataforma,
fue creado por Yukihiro Matsumoto en 1993 y presentado públicamente en 1995. La sintaxis del
lenguaje esta inspirada en otros lenguajes como Perl y Python, además posee características de
programación orientada a objetos. Además comparte funcionalidad con otros lenguajes de
programación como Lisp, Lua, Dylan y CLU.
Su implementación oficial es distribuida bajo una licencia de software libre.
19
El nombre del lenguaje procede de una broma en alusión al nombre del lenguaje Perl, ya que
ambos hacen referencia a nombres de piedras preciosas.
La última versión estable del lenguaje hasta este momento es la 1.8.6 que fue publicada en
Diciembre del 2007, mientras que ese mismo mes apareció la versión 1.9.0 que es una versión de
desarrollo que presenta varias mejoras.
2.9.1 Filosofía del lenguaje.
El creador de este lenguaje ha expresado que su creación fue hecha pensando en la
productividad así como la facilidad y diversión para el programador, es por eso que presenta una
buena interfaz al usuario, dándole un mayor énfasis a las necesidades del programador que a las de
la máquina.
El lenguaje sigue un principio llamado “principio de la menor sorpresa”, que quiere decir
que el lenguaje debe generar la menor confusión de los usuarios experimentados, esto debido a que
el creador decidió hacer un lenguaje que fuera capaz de hacer la programación más divertida para el
mismo, minimizando el trabajo a la hora de programar y evitando confusiones.
2.9.2 Semántica.
En este lenguaje todos los tipos de datos son considerado como un objeto, incluyendo las
clases y los tipos que en otros lenguajes son definidos como primitivas. Todas las funciones don
métodos y las variables son referencias a objetos, pero nunca un objeto por si solas.
Permite además utilizar programación procedural, es decir que se pueden definir funciones y
y variables fuera de las clases, todas estas definiciones serán parte de un objeto raíz llamado Object.
En Ruby no se requiere de polimorfismo de funciones ya que en todas las funciones se
pueden pasar datos de distinta clase en cada llamada del método, debido a que el lenguaje maneja
tipos de datos dinámicos.
20
El polimorfismo de tipos si es soportado, es decir que se pueden manejar clases utilizando la
interfaz de su clase padre.
2.9.3 Sintaxis.
La sintaxis de este lenguaje es muy parecida a la de Perl y Python. Las clases y los métodos
se definen con palabras claves.
Las variables pueden llevar prefijos para indicar el rango de valores que puede tomar esa
variable.
Las palabras claves se utilizan para definir valores sin utilizar llaves, a diferencia de otros
lenguajes como Perl y C. Los saltos de línea son interpretados como el final de una sentencia, el
punto y coma también se puede utilizar para dicho propósito.
En Ruby las variables de clases privadas se mantienen dentro de ellas, y solo se pueden
utilizar a travez de métodos de acceso. Se obliga a todas las variables de clases a ser privadas pero
también se proporciona una forma sencilla de utilizar métodos de acceso a ellas.
2.9.4 Metaprogramación.
La metaprogramación es una de las características de Ruby. Consiste en crear programas que
puedan manipular o inclusive crear otros programas como datos, o realizar durante la compilación
parte del trabajo que se realizaría durante la ejecución de otra forma.
Esta característica permite al programador ahorrar tiempo de desarrollo de código.
El compilador es la herramienta que comúnmente utiliza la metaprogramación, ya que
permite al programador realizar un programa en un lenguaje de alto nivel y luego lo traduce a
lenguaje ensamblador, lo cual ahorra mucho tiempo.
2.10 Modelo Vista Controlador [9] [10].
El Modelo Vista Controlador es un patrón de diseño de software que se utiliza en el diseño
de aplicaciones con interfaces sofisticadas.
21
Este patrón permite separar una aplicación en tres componentes distintos: La lógica de
control, los datos y la interfaz de usuario.
Es utilizado comúnmente en aplicaciones web en donde la vista es el código HTML y otros
códigos que permiten desplegar datos dinámicamente, el modelo es el sistema gestor de bases de
datos y la lógica de negocio mientras que el controlador es el mecanismo que recibe los eventos
desde la vista.
2.10.1 Descripción del patrón.
El patrón esta conformado por tres elementos como se mencionó:
Modelo: El modelo es el encargado de acceder a la capa de almacenamiento de datos,
además de definir la funcionalidad del sistema. Además debe llevar un registro de las vistas y
controladores del sistema, para que sea capaz de notificar a estos sobre los cambios que pueda
producir un agente externo a los datos.
Vista: La vista se encarga de recibir los datos de un modelo y mostrarlos al usuario. Debe
tener además un registro del controlador que por lo general es instanciado por esta fase. Presenta el
modelo en un formato que pueda interactuar con el usuario, por lo general es la interfaz del usuario.
Controlador: Es el encargado de recibir los eventos de entrada e interpretarlos para
determinar la acción que debe realizar cada evento. Por ejemplo cuando un usuario realiza un clic
sobre un botón el controlador debe recibir la solicitud y determinar la acción a realizar.
2.11 Ruby on Rails [6] [11].
Ruby on Rails es un framework para diseño de aplicaciones web de código abierto escrito en
el lenguaje Ruby. Este sigue el paradigma de la arquitectura de Modelo Vista Controlador (MVC).
Un framework es una estructura de desarrollo de software a partir de la cual se pueden
desarrollar otros proyectos. Por lo general incluye soporte de programas, bibliotecas y lenguaje
interpretado que permite unir los componentes del proyecto.
22
Ruby on Rails fue escrito por David Heinemeier Hansson y liberado al público por primera
vez en el año 2004. A partir de ese momento se han lanzado varias versiones, siendo la más actual
la versión 2.1 publicada el 1 de Junio del 2008.
La principal característica de este framework es que permite desarrollar aplicaciones de
utilidad en el mundo real de una forma sencilla, reduciendo la cantidad de código y de
configuración necesarios con respecto a otras opciones.
La metaprogramación propia del lenguaje Ruby es utilizada por Ruby on Rails para permitir
una sintaxis más legible para los usuarios.
Existen muchos proyectos y páginas conocidos que utilizan Ruby on Rails, que aunque es
muy reciente ha tenido gran aceptación entre los usuarios además que posee gran documentación en
línea para facilitar la ayuda a desarrolladores.
2.11.1 Principios Fundamentales.
Ruby on Rails utiliza dos principios fundamentales como lo son el principio de “No te
repitas” y el de “Convención sobre Configuración”.
El principio de “No te repitas” se refiere al hecho de realizar las definiciones una sola vez.
Es por eso que a la hora de programar los componentes se integran de manera que no es necesario
establecer puentes entre ellos ya que el mismo sistema los realiza, por ejemplo si se quiere definir
una clase no es necesario especificar los nombres de las columnas sino que son identificadas
automáticamente a través de la base de datos.
El principio de “Convención sobre Configuración” busca que el programador únicamente
deba especificar las configuraciones que no sean convencionales. Esto permite que al realizar una
base de datos partiendo de cero, se puedan seguir las convenciones propias de Ruby on Rails lo que
ahorra código.
2.11.2 El Modelo Vista Controlador de Ruby on Rails.
23
Ruby on Rails presenta un patrón Modelo Vista Controlador definido, los elementos de este
modelo son los siguientes:
Modelo: El modelo consiste básicamente en las clases que son la representación de las
diferentes tablas de la base de datos. Para acceder a las clases del modelo se debe únicamente
heredar la clase ActiveRecord::Base y el programa encontrará que tabla debe utilizar y que
columnas posee dicha tabla.
Al definir una clase se detalla a su vez las relaciones entre las clases mediante una estructura
objeto relacional.
Las rutinas para validación de datos así como las de actualización también son especificadas
e implementadas en el modelo.
Vista: La vista presenta la lógica que permite la visualización de los datos de las clases del
Controlador. Esta es considerada por lo general para aplicaciones web como el código incluido en
HTML.
En Rails se utiliza un modelo de Ruby integrado, que utiliza archivos con formato RTML.
Estos están compuestos por códigos HTML, mezclados con código de Ruby. También se pueden
construir vistas en HTML o XML.
Cada método del controlador debe llevar un código en HTML para mostrar información al
usuario. La distribución de los elementos de la página se describe separadamente de las acciones del
controlador.
Controlador: Estas clases son las que responden a la interacción con el usuario y
determinan la lógica que se debe seguir cuando se da un evento, para manipular los datos de las
clases y mostrar los resultados a través de la vista. Estos métodos son invocados por el usuario
utilizando un navegador web en aplicaciones de este tipo.
El controlador es implementado en Ruby on Rails por el ActionPack. A partir de la clase
24
ApplicationController se pueden heredar otras clases para definir acciones como métodos para
invocar a través del navegador web.
Ruby on Rails permite construir de forma rápida la mayor parte de la lógica de control y las
vistas necesarias para las operaciones más comunes.
2.11.3 Soporte de bases de datos.
Ruby on Rails proporciona soporte para la utilización de bases de datos, favoreciendo su uso
a través de un gestor de bases de datos. Se soporta la biblioteca SQLite en caso de que no se pueda
utilizar una base de datos. La interacción con la base de datos es abstracta desde el punto de vista
del programador, y los accesos son realizados automáticamente sin necesidad de utilizar consultas
de tipo SQL aunque de querer usarse se pueden utilizar.
Entre los sistemas gestores de base de datos soportados se encuentran: MySQL, PostgreSQL,
SQLite, IBM DB2, Oracle y Microsoft SQL Server.
25
CAPÍTULO 3: Estructura general del sistema de inventario de
bodega.
3.1 Estructura de la aplicación y aspectos generales.
La base de datos del sistema desarrollado esta dividida en dos partes esenciales: Una base
de datos que maneja los activos de la bodega, con sus diferentes marcas, modelos y estados de los
activos, y otra tabla que maneja los usuarios en la cual se almacena la información personal de estos
así como la información utilizada para la conexión de estos al sistema como lo son el nombre de
usuario y las contraseñas.
Para la base de datos se utilizó el gestor de base de datos PostgeSQL, que es de uso libre,
además de ser uno de los más reconocidos por su excelente manejo de datos permitiendo conservar
su integridad y coherencia.
La aplicación se desarrollo en el lenguaje de programación Ruby utilizando el framework
Ruby on Rails, el cual permite implementar el manejo de la base de datos de una forma más
sencilla, ahorrando al programador mucho código que se puede hacer genérico para todas las
aplicaciones.
La aplicación utiliza una estructura modelovistacontrolador, por lo tanto los códigos estas
clasificados según estas tres secciones. Todos estos archivos relacionados directamente con la
aplicación se encuentran en la carpeta “app”, divididos en carpetas separadas para cada una de las
secciones.
Además existen varios archivos de configuración así como librerías utilizadas entre otras
cosas.
3.2 Base de datos.
Como ya se mencionó se utiliza es gestor de base de datos PostgreSQL, para el desarrollo de
la aplicación se utilizó la versión 8.3.3.
26
Se utiliza un adaptador que se encarga de realizar el manejo de la base de datos, incluyendo
la creación de las bases de datos a utilizar y la creación de sus tablas, traduciendo código Ruby en
sentencias SQL para realizar dichas tareas.
La base de datos se encarga del almacenamiento de forma segura y confiable de la
información, tanto de activos de bodega como de usuarios, sesiones y roles utilizados para la
autenticación al sistema.
3.3 Modelo.
El modelo es la parte encargada del manejo directo de la base de datos y sus relaciones. Es la
representación de la base de datos desde la aplicación, de manera que maneja las tablas y sus
elementos como clases, de manera que se pueda hacer referencia a ellas de una forma sencilla desde
cualquier parte del código.
En esta parte se definen además las sentencias de mapeo objetorelacional que describen la
relación entre las clases, es decir entre los elementos de las tablas de la base de datos.
Además se definen las rutinas de validación de datos que permiten conservar la integridad
de los mismos, especificando que reglas se deben seguir antes de introducir un valor a la base de
datos.
Se definen también algunas funciones que requieren la revisión o manipulación directamente
de los valores de la base de datos, por ejemplo si se quiere encriptar la contraseña de los usuarios se
puede definir aquí la función que realice dicha tarea.
Entre las funciones que se puede definir esta también funciones para filtrar los datos
ingresados mediante expresiones regulares que permitan eliminar caracteres indeseados en una
entrada de un valor a la base de datos.
3.4 Controlador.
El controlador es el encargado de manejar los eventos que se realizan en la aplicación, por lo
27
general provocados por una acción del usuario.
Se tienen controladores separados para cada tabla de la base de datos, por defecto, aunque se
pueden crear nuevos controladores para otras acciones.
Las acciones básicas que maneja el controlador son las de nuevo, crear, editar, actualizar,
destruir y listar y mostrar.
Nuevo: Cuando se quiere crear un nuevo elemento esta acción se encarga de crear un
elemento en blanco que luego es actualizado con los datos que se ingresan por el usuario. La
necesidad de crear un elemento en blanco es que de esta forma se puede asignar en la vista un
campo de la variable a cada elemento de la forma que debe llenar el usuario.
Crear: La acción de crear se encarga de tomar los datos ingresados por el usuario y
actualizar el elemento que previamente fue creado con la acción nuevo.
Editar: Editar se encarga de asignar en la vista los valores actuales de el elemento a editar
de forma que el usuario lo modifique a placer.
Actualizar: Toma los elementos modificados por el usuario en la vista de editar, y los
actualiza en la base de datos.
Destruir: Destruye el o los elementos seleccionados, eliminándolo de la base de datos.
Listar: Hace una búsqueda y muestra una lista de los elementos que el usuario desea ver.
Mostrar: Muestra el contenido de un elemento específico que el usuario quiere ver.
En algunos casos hay acciones que no se necesitan, como por ejemplo en el caso de las
sesiones, estas se crean cuando un usuario se conecta al sistema, sin embargo no es necesario
editarlas ni actualizarlas, simplemente se eliminan cuando el usuario se desconecta, por lo tanto
dichas acciones no están definidas para este caso.
3.5 Vista.
La vista maneja la interfaz del sistema con el usuario. Esta dividida también según el
28
elemento a desplegar y la acción que se va a realizar. Por ejemplo existe una vista para listar los
activos, otra con la forma para que el usuario cree un nuevo activo con los datos requeridos, otra
muy similar a la anterior con una forma que despliega los datos actuales de el activo para ser
modificados por el usuario, así como una vista para mostrar los datos de un activo específico.
Estas vistas se encargan de comunicarse con el controlador para tomar los datos que este le
pide al modelo y desplegarlos en pantalla al usuario.
Las vistas están en lenguaje HTML, sin embargo poseen código Ruby integrado mediante
una sentencia especial que permite insertar estos códigos.
Aparte de una vista para cada acción a realizar exista una archivo de máscara o layout que
maneja una interfaz alrededor de la pantalla donde se despliegan los datos, es decir, maneja la barra
de título de la aplicación, la barra lateral y en fin, la estructura general de la interfaz con el usuario.
Ruby on Rails crea un layout por defecto para cada una de las tablas, sin embargo, en nuestra
aplicación se utilizó un único layout para desplegar todas las vistas, el cual fue llamado
“aplicación.html.rb”. El layout utilizado no posee ninguna descripción de estilos y formatos, para
esto se utiliza un archivo nombrado “inventario.css” el cual esta escrito en un lenguaje de Hoja de
estilo en cascada (CSS), en el cual se especifican los tipos y tamaños de letra, el color y las
tabulaciones de los diferentes elementos de las tablas.
3.6 Archivos de configuración.
Los archivos de la carpeta “config” poseen la configuración de la aplicación, donde se puede
definir configuraciones para los diferentes ambientes de trabajo, así como la configuración de la
base de datos, las rutas por defecto para las vistas e información relacionada con los plugins
instalados para la aplicación.
Los archivos de configuración más importantes son:
database.yml: En este archivo se especifica las características de la base de datos a utilizar.
29
El nombre de la base de datos, el adaptador para manejar dicha base de datos, la codificación, el
usuario de la base de datos y la contraseña son los elementos descritos en este archivo, para cada
uno de los ambientes de trabajo, ya sea desarrollo, producción o prueba.
environment.rb: En este archivo posee información relacionada con las “gemas” instaladas y
que la aplicación va a utilizar. Las gemas son bibliotecas de Ruby que se administran de forma
sencilla con el comando “gem” desde la terminal.
routes.rb: En este archivo se especifica las rutas por las cuales se va a invocar las diferentes
vistas en el navegador. Además se especifica la ruta por defecto de la aplicación.
3.7 Otras carpetas.
El sistema esta compuesto por otras carpetas que contienen también información importante
para el funcionamiento de la aplicación. A continuación se resume la función y contenido de las
más relevantes:
db: Tiene información de la base de datos. En ella se guarda el código de las diferentes
migraciones realizadas para la base de datos. Las migraciones permiten modificar las bases de datos
sin comprometer la integridad de los datos existentes.
Además en el archivo “schema.rb” se presenta la descripción de la estructura actual de la
base de datos, así como la versión de la migración que se esta corriendo.
lib: Contiene información de bibliotecas instaladas el el proyecto. En la aplicación realizada
contiene archivos de uno de los plugins instalados, necesarios para su buen funcionamiento.
log: Contiene un registro de las notificaciones desplegadas por el sistema durante todo el
desarrollo de la aplicación. Así como algunas notificaciones de algunos de los plugins utilizados
que permiten revisar las acciones que se han realizado.
public: Posee archivos web que no cambian como las imágenes, las hojas de estilo y los
archivos en lenguaje JavaScript, además de algunos archivo en HTML.
30
script: Esta carpeta contiene scripts para poder correr varias herramientas que se utilizan
con Ruby on Rails. Entre los scripts que se pueden encontrar están los utilizados para generar
código y el que se utiliza para arrancar el funcionamiento del servidor de desarrollo.
vendor: Este directorio contiene bibliotecas desarrolladas por terceros, es decir que no
corresponden a la distribución de Ruby on Rails. Por ejemplo aquí se encuentran las bibliotecas
utilizadas por los plugins instalados dentro de la carpeta del proyecto.
Index: Esta carpeta es creada por el plugin “Actasferret”. En ella se guardan los índices
generados por las búsquedas que se hayan realizado de manera que las búsquedas subsiguientes
puedan utilizar esta información para agilizar el tiempo de respuesta de dicha búsqueda.
3.8 Plugins utilizados.
Se utilizaron 6 plugins para el desarrollo de la aplicación. Tres de ellos se utilizaron para
poder crear llaves foráneas para realizar las relaciones entre las tablas y aumentar la confiabilidad
del sistema en el manejo de los datos. Muchas referencias indicaban que en Ruby on Rails no era
necesario crear estas llaves foráneas, ya que la aplicación se encarga de manejar la relación entre los
datos. Sin embargo, la creación de estas llaves permite un manejo más seguro y confiable de estos
datos ya provoca que el propio sistema gestor de base de datos compruebe estas relaciones.
Los tres plugins utilizados para este propósito fueron:
redhillonrails_core: Este plugin contiene bibliotecas necesarias para el funcionamiento de los otros
dos plugins.
foreign_key_migrations: Crea llaves foráneas en la base de datos automáticamente a la hora de
realizar una migración de la base de datos. Se pueden especificar de varias formas las llaves
foráneas deseadas en el sistema. Al crear una columna de la forma “cosa_id”, este automáticamente
crea una llave foránea usando el identificador de la tabla “cosas”
foreign_key_associations: Crea automáticamente relaciones en el modelo basado en las llaves
31
foráneas existentes en la base de datos.
Los otros tres plugins utilizados en fueron:
Restful_authentication: Crea una estructura base para la creación de un sistema de autenticación de
usuarios.
acts_as_ferret: Realiza búsquedas en la base de datos del sistema. Permite utilizar varias funciones
para búsquedas con diferentes parámetros.
will_paginate: Utilizado para la paginación de los elementos desplegados en pantalla. Se consideró
que al crecer la base de datos es mejor desplegarla de una manera más ordenada como lo es
mediante páginas, especificando un número razonable de elementos por página de manera que si se
desea cargar una tabla con muchos elementos la página cargue estos por secciones aumentando la
velocidad de navegación de la página web.
32
CAPÍTULO 4: Diseño de la base de datos.
Como se explicó anteriormente, la base de datos esta dividida en dos secciones principales.
El primer conjunto de tablas se encarga de almacenar la información objetivo del sistema, es decir la
información de los activos de inventario junto con sus marcas, modelos y estados.
La otra parte de la base de datos es la encargada de almacenar la información de los usuarios
creados en el sistema que es utilizada por el sistema de autenticación. Aquí se tiene una tabla para
información de los usuarios, otra en la que se almacenan los roles existentes y una que contiene la
información que describe cuales roles posee cada usuario.
4.1 Base de datos para activos de bodega.
Para diseñar esta parte de la base de datos se investigó con el encargado de la bodega de la
Escuela de Ingeniería Eléctrica de la Universidad de Costa Rica, cual era la información importante
que debía poseer cada uno de los activos de bodega y cuales clasificaciones era importante realizar
con estos.
La información que se debe almacenar en la base de datos es la siguiente:
Cuadro 1. Activos en nivel de normalización 0.
Activos
#Placa #Serie Modelo Descripción Marca Estado
Aplicando la primera regla de normalización de bases de datos se agrega un identificador a
la tabla. Se consideró la opción de utilizar el número de placa como identificador, sin embargo la
posibilidad de que este número de placa no exista o este repetido evita que se pueda utilizar para
esto. Una vez incluida la columna del identificador se tiene:
Cuadro 2. Activos en nivel de normalización 1.
Activos
Activo Id #Placa #Serie Modelo Descripción Marca Estado
33
El segundo nivel de normalización indica que se deben de crear tablas separadas para los
grupos de datos que apliquen a varios registros. En nuestro no existe ningún grupo de datos que este
aplicado varias veces a un registro por lo tanto no es necesario realizar ningún cambio.
El tercer nivel de normalización indica que se deben de eliminar los campos que no
dependen de la clave. Podemos notar como el modelo con su respectiva descripción es
independiente de cada activo individual, por lo cual se puede separar en una nueva tabla. De igual
forma el estado del equipo es independiente de la clave primaria de el activo de manera que la
estructura de tablas se convierte en la siguiente:
Cuadro 3. Activos en nivel de normalización 2.
Activos
Activo Id #Placa #Serie Rel. Modelo_id Rel. Estado_id
Cuadro 4. Estados en nivel de normalización 2.
Estados
Estado Id Nombre_estado
Cuadro 5. Marcas en nivel de normalización 2.
Modelos
Modelo_id Nombre_Modelo Descripción Marca
Pero podemos notar como en esta última tabla la marca puede aplicarse también a varios
modelos por lo que esta no depende de la llave primaria de dicha tabla por lo que se crea una tabla
separada para las marcas y se relacionan las tablas mediante una llave foránea, de la siguiente
forma:
Cuadro 6. Modelos en nivel de normalización 3.
34
Modelos
Modelo_id Nombre_Modelo Descripción Rel. Marca_id
Cuadro 7. Marcas en nivel de normalización 3.
Marcas
Marca Id Nombre_marca
Figura 2. Diagrama ER sistema de manejo de activos.
Tenemos ahora cuatro tablas separadas. El cuarto nivel de normalización se dice que se debe
aplicar en situaciones en las que se da una relación de varios con varios. En nuestro caso no es
necesario este nivel por lo tanto se considera que el tercer nivel es suficiente para que se de un
manejo fácil y seguro de los datos.
4.2 Base de datos para manejo de usuarios.
La segunda parte de la base de datos es la que esta relacionada con el manejo de usuarios del
sistema. En esta parte se utilizó un esquema siguiendo algunos lineamientos brindados por el plugin
35
instalado para dicho propósito. Además se decidió añadir algunos campos para información
personal de los usuarios como lo son el nombre, el teléfono, número de cédula y carné en caso de
existir.
El esquema posee 3 tablas: Una tabla de usuarios con la información de estos, una de roles,
con los datos de los diferentes roles creados y una tabla de permisos en la cual se relacionan los
usuarios con diferentes roles para de esta forma asignar los permisos a los usuarios según el nivel de
acceso a la aplicación deseado para cada uno de ellos.
La base de datos de usuarios contiene las siguientes columnas:
● Id_usuario: El identificador de la tabla.
● Login: El nombre del usuario en el sistema.
● Email: El correo electrónico.
● crypted_password: La contraseña encriptada.
● Salt: Variable utilizada para la encriptación de los datos.
● remenber_token: Un identificador para ser recordado por el sistema en un computador
específico.
● remember_token_expires_at: El tiempo de vencimiento del identificador.
● Nombre: El nombre de la persona asignada a dicho usuario.
● Apellido: El apellido de la persona asignada a dicho usuario.
● Teléfono: El número telefónico del usuario.
● Cédula: La cédula de identidad de la persona.
● Carné: En caso de ser estudiante se almacena la información de su carné.
La tabla de roles almacena el nombre de los roles existentes en el sistema, de manera que se le
pueda asignar dicho rol a un usuario para brindarle permisos especiales a este. La tabla posee la
36
siguiente información:
Cuadro 8. Tabla de roles.
Roles
Role_Id Rolename
La tabla de permisos almacena la información de cuales usuarios están relacionados con
ciertos roles, es decir, los permisos que cada usuario posee en el sistema:
Cuadro 9. Tabla de permisos.
Permisos
Permissions_Id role_Id User_Id
El archivo “schema.rb” de la carpeta “db” nos muestra finalmente la estructura de la base de datos
con sus llaves foráneas respectivas.
ActiveRecord::Schema.define(:version => 20081126080143) do
create_table "activos", :force => true do |t| t.string "num_serie" t.integer "placa" t.integer "modelo_id" t.integer "estado_id" t.datetime "created_at" t.datetime "updated_at" end
create_table "estados", :force => true do |t| t.string "nombre" t.datetime "created_at" t.datetime "updated_at" end
create_table "marcas", :force => true do |t| t.string "nombre_marca" t.datetime "created_at" t.datetime "updated_at"
37
end
create_table "modelos", :force => true do |t| t.string "nombre_modelo" t.string "descripcion" t.integer "marca_id" t.datetime "created_at" t.datetime "updated_at" end
create_table "permissions", :force => true do |t| t.integer "role_id", :null => false t.integer "user_id", :null => false t.datetime "created_at" t.datetime "updated_at" end
create_table "roles", :force => true do |t| t.string "rolename" t.datetime "created_at" t.datetime "updated_at" end
create_table "users", :force => true do |t| t.string "login" t.string "email" t.string "crypted_password", :limit => 40 t.string "salt", :limit => 40 t.datetime "created_at" t.datetime "updated_at" t.string "remember_token" t.datetime "remember_token_expires_at" t.string "nombre" t.string "apellido" t.integer "telefono" t.string "carne" t.integer "cedula" end
add_foreign_key "activos", ["modelo_id"], "modelos", ["id"], :name => "activos_modelo_id_fkey" add_foreign_key "activos", ["estado_id"], "estados", ["id"], :name => "activos_estado_id_fkey"
add_foreign_key "modelos", ["marca_id"], "marcas", ["id"], :name => "modelos_marca_id_fkey"
add_foreign_key "permissions", ["role_id"], "roles", ["id"], :name => "permissions_role_id_fkey" add_foreign_key "permissions", ["user_id"], "users", ["id"], :name => "permissions_user_id_fkey"
end
Entre las cosas que se puede notar es que Ruby on Rails al crear una tabla, crea
automáticamente en ella dos columnas correspondientes a la fecha de creación y a la fecha de
actualización del elemento, este valor se almacena automáticamente a la hora de crear y de editar un
38
elemento respectivamente. Esto permite llevar un seguimiento por fecha de las modificaciones en la
base de datos y puede ser muy útil en algunos casos.
Para llegar a la estructura anterior de la base de datos se debieron realizar varias migraciones
de esta, ya que conforme avanzó el desarrollo de la aplicación, se encontraron nuevos
requerimientos y se necesito realizar algunos cambios.
De igual manera de necesitarse en el futuro agregar nuevos elementos o cambiar la
estructura de la base de datos, se puede realizar de manera sencilla mediante migraciones.
39
CAPÍTULO 5: Modelo.
El modelo es la sección del programa encargada de hacer el manejo directo de la base de
datos. En el se definen los elementos de una tabla como objetos de Ruby y además se hace la
validación de los datos introducidos, para definir las reglas en el manejo de los datos que
contribuyan a cuidar la integridad de estos.
Existe un modelo para cada una de las tablas presentes en la base de datos.
5.1 Modelos del sistema de activos.
activos.rb:
class Activo < ActiveRecord::Base
belongs_to :estado belongs_to :modelo acts_as_ferret :fields => [:num_serie, :placa]
def self.per_page 40 end
validates_uniqueness_of :placavalidates_numericality_of :placa, :allow_nil => true validates_presence_of :num_serie, :placa
end
Podemos ver como se definen las relaciones en entre las tablas. En este caso se especifica
que cada modelo pertenece a un estado y a un modelo.
La sentencia “acts_as_ferret” es utilizada por el plugin del mismo nombre. Mediante esta se
especifica que se va a utilizar el sistema de búsquedas en las columnas especificadas luego entre
paréntesis.
Se consideró que las búsquedas de los activos se debían realizar por su número de serie o por
su placa. De esta manera se puede encontrar un activo específico cuando se necesite.
La sentencia “def_self.per_page” define el número de elementos que se debe desplegar por
página. Este número es el parámetro que utiliza el plugin de paginación para saber como acomodar
los elementos por página y es muy sencillo cambiarlo para ajustarlo al gusto del usuario.
40
Se quiere que el valor de la placa sea un valor único, y además que sea siempre un número,
por lo que se indica que se debe validar este dato para comprobar que sea un número.
Finalmente se especifica que tanto el número de serie como la placa deben estar presentes,
de otra forma no se permite crear o editar el activo.
estados.rb:
class Estado < ActiveRecord::Base has_many :activos
end
En este modelo se define únicamente la relación entre los estados y los activos. Se especifica
entonces que cada estado tendrá muchos activos asignados.
modelo.rb:
class Modelo < ActiveRecord::Base belongs_to :marca has_many :activos acts_as_ferret :fields => [:descripcion, :nombre_modelo]
end
En este caso se especificó que los modelos pertenecen a una marca. Además cada modelo
posee varios activos.
Para este caso se aplicó también el sistema de búsquedas y se especifico que estas se pueden
realizar en la columna de nombre del modelo así como en su descripción.
modelo.rb:
class Marca < ActiveRecord::Base has_many :activos, :through => :modelos has_many :modelos acts_as_ferret :fields => [:nombre_marca]
end
En el caso de las marcas, se define que estas tienen muchos modelos, además como cada
modelo posee varios activos, se especifica que cada marca tiene muchos activos a través de los
modelos.
41
De nuevo se utiliza el plugin para búsquedas, en este caso se realizan búsquedas en la
columna de nombre de la marca.
5.2 Modelos del sistema de autenticación de usuarios.
Como se menciono anteriormente tenemos una tabla de permisos usuarios que almacena la
información de todos los usuarios registrados en el sistema. Además existe una tabla de roles que
posee una identificación de los roles existentes y una tabla de permisos que posee la información de
cuales usuarios poseen cuales permisos. A cada usuario se le puede asignar varios permisos, es
decir varios roles.
user.rb:
attr_accessor :password acts_as_ferret :fields => [:login, :email, :nombre, :apellido, :telefono, :carne, :cedula] validates_presence_of :login, :email validates_presence_of :password, :if => :password_required? validates_presence_of :password_confirmation, :if => :password_required? validates_length_of :password, :within => 4..40, :if => :password_required? validates_confirmation_of :password, :if => :password_required? validates_length_of :login, :within => 3..40 validates_length_of :email, :within => 3..100 validates_uniqueness_of :login, :email, :case_sensitive => false validates_numericality_of :telefono validates_numericality_of :cedula has_many :permissions has_many :roles, :through => :permissions before_save :encrypt_password
Las anteriores sentencias definen la validación de datos para los usuarios. En este caso
tenemos que se activan las búsquedas en el nombre del usuario, en el correo electrónico, en el
nombre y apellido de la persona, el teléfono, carné y cédula.
Además se define que tanto el nombre de usuario, como el correo, la contraseña y su
confirmación deben estar presentes a la hora de crear un usuario, de otra forma se presenta un error.
El nombre de usuario y el correo electrónico deben tener un largo determinado para ser
válidos, por lo que se especifica un largo mínimo de 3 caracteres en ambos casos y un máximo de
40 y de 100 para el nombre de usuario y el correo respectivamente. Estos deben ser únicos además.
42
La validación de datos especifica además que los campos de nombre de usuario y correo
deben ser únicos.
Los campos de teléfono y número de cédula deben ser solo números, de esta manera se evita
que se ingresen caracteres no deseados a la tabla que pueden alterar el dato que se quiere.
En cuanto a las relaciones con otras tablas, se define que los usuarios tienen muchos
permisos, y a su vez tienen muchos roles a través de los permisos.
En este archivo además se especifican varias funciones que tienen que ver con el chequeo de
la base de datos. Entre estas funciones se encuentran las que se encargan de encriptar los datos de
las contraseñas, las que se encargan de recordar un usuario en un equipo y otras funciones a las
cuales no se les dio un uso en nuestra aplicación ya que algunas funcionalidades como la activación
por correo no eran necesarias según los requerimientos de la aplicación.
role.rb:
class Role < ActiveRecord::Base has_many :permissions has_many :users, :through => :permissions end
El modelo de los roles define únicamente que estos poseen varios permisos y que además a
través de estos permisos posee muchos usuarios.
permissions.rb:
class Permission < ActiveRecord::Base belongs_to :user belongs_to :role end
En el caso de los permisos se puede notar que el modelo especifica que estos pertenecen a
usuarios y a roles al mismo tiempo. De esta manera se maneja en esta tabla la relación entre los
usuarios y los roles, quedando finalmente una relación de muchos contra muchos, ya que un usuario
43
puede tener varios roles y a su vez un rol puede estar asociado a varios usuarios al mismo tiempo.
44
CAPÍTULO 6: Controladores.
Los controladores son las partes del código encargadas de realizar las acciones que el
usuario ordene. Estas pueden ir desde desplegar elementos en pantalla, hasta hacer modificaciones a
la base de datos agregando, quitando o modificando elementos en esta.
Las acciones básicas que Ruby on Rails define por defecto son: Nuevo, crear, editar,
actualizar, destruir, mostrar y listar.
Se sabe que Ruby on Rails crea estas acciones por defecto al crear la estructura para cada
una de sus tablas. En varios controladores de la aplicación estas acciones no fueron modificadas,
por lo tanto son idénticas en varios controladores. Por lo tanto se va a comentar estas una única vez
y además se van a explicar los cambios realizados en el caso de haberlos.
6.1 Controladores de sistema de activos.
Se tienen como se mencionó muchos códigos que son similares en los controladores de el
sistema de activos. Debido a esto se menciona primero los códigos que son similares en todos los
casos, con el objetivo de evitar la explicación repetida de códigos.
Las siguientes líneas están presentes en todos los controladores de el sistema de activos
como lo son: Activos, modelos, marcas y estados.
include AuthenticatedSystem layout 'application' before_filter :login_required, :only => [:show, :index] before_filter :check_administrator_role, :only => [:destroy,:new, :edit, :update]
Al inicio del archivo tenemos las sentencias anteriores. En ellas se define que se va a incluir
las librerías del sistema de autenticación de usuarios, esto para utilizar seguidamente algunas
funciones para aplicar los filtros a las acciones del controlador.
Se define que se va a utilizar el layout “application”, el cual fue creado como una máscara
genérica para todos los controladores. Esto se explicará más adelante en el capítulo de vistas.
Se definen además los filtros a la página. Mediante esto se puede generar permisos de
45
ingreso a las diferentes acciones del controlador. En este caso y en el de los otros controladores del
sistema de activos, si un usuario se encuentra conectado al sistema. En caso de que este se dé, el
usuario tiene acceso a las funciones de mostrar y de listar. Sin embargo si además de estar
conectado, el usuario posee un permiso de administrador, se le brinda acceso a las funciones que
realizan modificaciones de la base de datos, como lo son las de crear, editar y destruir elementos.
def index @estados = Estado.find(:all)
respond_to do |format| format.html # index.html.erb format.xml { render :xml => @estados } end end
El método de listar mostrado anteriormente permite encontrar todos los elementos presentes
en la tabla, mediante la función “find” que tiene como parámetro “:all” lo cual indica que se deben
buscar todos los elementos presentes.
Las siguientes líneas son funciones que utiliza Ruby para determinar si se debe desplegar la
página en código HTML o en XML. Esto depende de las extensiones de los archivos creados en las
vistas. Mediante esto Ruby genera automáticamente el código para desplegar lo que se desee, en el
formato que se decida.
def show @estado = Estado.find(params[:id])
respond_to do |format| format.html # show.html.erb format.xml { render :xml => @estado } end end
El método de mostrar es muy similar al anterior, con la diferencia que en este caso se
selecciona únicamente uno de los elementos de la tabla, especificando en la función “find” el
identificador de este elemento, mediante “:id”.
def new
46
@estado = Estado.new
respond_to do |format| format.html # new.html.erb format.xml { render :xml => @estado } end end
El método de “nuevo” permite crear un elemento vacío para desplegar una forma donde el
usuario pueda asignar los valores deseados al elemento. Esto permite asignar una variable del
elemento a cada uno de los campos de la forma para luego pasarle dichos parámetros introducidos
por el usuario al método de “crear” para que este cree el elemento con estos parámetros.
def create @estado = Estado.new(params[:estado])
respond_to do |format| if @estado.save flash[:notice] = 'El estado fue creado.' format.html { redirect_to(@estado) } format.xml { render :xml => @estado, :status => :created, :location => @estado } else format.html { render :action => "new" } format.xml { render :xml => @estado.errors, :status => :unprocessable_entity } end end end
Como se mencionó anteriormente este método permite crear un nuevo elemento (en este
caso un estado) con los parámetros introducidos por el usuario, que se indican a través de la
sentencia “params[:estado]”. Además si el usuario es creado se especifica que se debe mostrar el
elemento creado en la siguiente página, y desplegar un mensaje indicando que el elemento fue
creado.
En caso de que no se haya podido crear el elemento se debe volver a la página “nuevo” para
modificar los parámetros.
def edit @estado = Estado.find(params[:id])
47
end
El método de editar simplemente busca un elemento con el número de identificación elegido
para agregar estos valores a la forma de manera que el usuario pueda modificar estos valores para
realizar los cambios que quiera.
def update @estado = Estado.find(params[:id]) respond_to do |format| if @estado.update_attributes(params[:estado]) flash[:notice] = 'El estado fue actualizado.' format.html { redirect_to(@estado) } format.xml { head :ok } else format.html { render :action => "edit" } format.xml { render :xml => @estado.errors, :status => :unprocessable_entity } end end end
El método de actualizar busca inicialmente el elemento que se va a modificar mediante el
identificador indicado para luego hacer un llamado a la función “update_attributes” que actualiza
los atributos de el elemento con los parámetros indicados entre paréntesis que provienen del
formulario de edición que se modificó anteriormente.
Se direcciona luego a mostrar el elemento modificado en caso de que dicha modificación se
haya realizado satisfactoriamente, además se despliega un mensaje indicando que dicho elemento
fue actualizado.
En caso de que no se pueda realizar la actualización se vuelve a la página de editar para
realizar los cambios correspondientes.
def destroy @estado = Estado.find(params[:id]) @estado.destroy
respond_to do |format| format.html { redirect_to(estados_url) } format.xml { head :ok } end end
48
El método de destruir busca el elemento que se desea eliminar a través de su identificador y
llama al método “destroy” que se encarga de eliminarlo de la base de datos. Posteriormente envía a
la página índice de los elementos.
En el caso de los activos el método de listar fue modificado de manera que si se indica un
estado o un modelo específico se despliegue solamente los activos que poseen ese atributo. Para
esto fue necesario pasar como parámetro a este método ya sea el identificador de el modelo o de el
estado según corresponda. En caso de que ninguno de los dos exista se despliegan todos los activos
existentes.
def index
if params[:q] query = params[:q] @activos = Activo.find_by_contents(query, :limit => :all)
else if (params[:estado_id].nil? and params[:modelo_id].nil?)
@activos = Activo.paginate :page => params[:page], :order => 'updated_at DESC' else if params[:modelo_id].nil?
@activos = Activo.paginate :page => params[:page], :conditions=> ["estado_id = ?", params[:estado_id]] else
@activos = Activo.paginate :page => params[:page], :conditions=> ["modelo_id = ?", params[:modelo_id]]
end end
end respond_to do |format| format.html # index.html.erb format.xml { render :xml => @activos } end end
Podemos notar como se verifica primero si existe algún parámetro de búsqueda, en caso de
que exista se llama a la funcion “find_by_contents” que proporciona el plugin “acts_as_ferret”,
mediante la cual se realiza la búsqueda de activos relacionados a el parámetro indicado.
Si no existe el parámetro anterior se revisa la existencia de algún otro parámetro, para
determinar cuales activos se deben desplegar. Si existe algún parámetro se revisa si es un
identificador de modelo o de estado y en cada caso se se busca los elementos con este identificador.
49
En el caso del controlador de los modelos se utiliza la misma lógica para determinar si existe
un parámetro de marca que haya sido enviado para desplegar únicamente los modelos
pertenecientes a dicha marca en caso de existir el parámetro. Además se verifica la existencia de un
parámetro de búsqueda también.
if params[:q]
query = params[:q] @modelos = Modelo.find_by_contents(query, :limit => :all)
else if params[:marca_id].nil? @modelos = Modelo.find(:all)
else @modelos = Modelo.find(:all, :conditions=> ["marca_id = ?", params[:marca_id]])
end
6.2 Controladores de sistema de autenticación de usuarios.
Entre los controladores del sistema de usuarios tenemos un controlador que maneja todo lo
correspondiente al manejo de los usuarios, es decir, la creación, edición, eliminación y despliegue
de estos. Además de esto se tiene un controlador para realizar la actualización de las contraseñas,
llamado “accounts”.
Otro controlador es el que se encarga del manejo de los roles. Este permite crear roles así
como asignarlos a usuarios.
El último controlador es el que se encarga de crear y destruir las sesiones, este permite que
una sesión sea recordada en un equipo específico.
users_controller.rb:
layout 'application' before_filter :login_required, :only => [:show, :edit, :update] before_filter :check_administrator_role, :only => [:index, :destroy, :new, :create]
Al igual que en los otros controladores discutidos, se especifica que se va a utilizar el layout
“application”. Seguidamente se definen los filtros para los usuarios. En este caso a un usuario
normal se le permite únicamente las acciones de “mostrar”, “editar” y “actualizar”, eso si estas las
50
podrá realizar solo sobre su propio usuario.
Al usuario administrador se le permite además crear, eliminar y ver usuarios.
El método de listar es sencillo y únicamente se le agregó la verificación de parámetros para
búsquedas.
def index if params[:q]
query = params[:q] @users = User.find_by_contents(query, :limit => :all)
else @users = User.find(:all)
end end
Los métodos de “mostrar”, “nuevo”, “editar”, “actualizar” y “destruir” son idénticos a los
explicados para el sistema de activos, por lo que se evitará su discusión.
sessions_controller.rb:
En este controlador se maneja la creación de sesiones de usuarios, es decir cuando un
usuario conecta al sistema se crea una sesión, la cual es destruida en el momento en que este usuario
se desconecta.
layout 'application' before_filter :login_required, :only => :destroy before_filter :not_logged_in_required, :only => [:new, :create]
Primero se define que se utilizará el layout “application” al igual que para todos los
controladores de la aplicación.
Además se aplican los filtros a los usuarios, de manera que si un usuario se encuentra
conectado, el sistema le permita destruir la sesión, es decir desconectarse. De igual forma si un
usuario no esta conectado se le permite crear una sesión, es decir conectarse al sistema.
def create password_authentication(params[:login], params[:password]) end
El método de “crear” llama el método “password_authentication” con los parámetros de el
51
nombre de usuario y la contraseña que hayan sido ingresados por el usuario.
def password_authentication(login, password) user = User.authenticate(login, password) if user == nil failed_login("Su nombre de usuario o contraseña es incorrecto.") else self.current_user = user successful_login end end
El método “password_authentication” a su vez llama el método “authenticate” del modelo
de los usuarios, que verifica la existencia de un usuario con los parámetros introducidos. En caso de
existir se iguala el usuario actual “current_user” a dicho usuario y se llama al método
“succesful_login”. En caso de no existir se llama al método “failed_login” introduciendo como
parámetro un mensaje de error indicando que el nombre de usuario o la contraseña no son correctos.
def failed_login(message) flash.now[:error] = message render :action => 'new' end
El método “failed_login” despliega el mensaje que se pasó como parámetro y envía de nuevo
a la página de ingreso al sistema.
def successful_login if params[:remember_me] == "1" self.current_user.remember_me cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at } end flash[:notice] = "Se ha conectado!" return_to = session[:return_to] if return_to.nil? redirect_to user_path(self.current_user) else redirect_to return_to end
El método “successful_login” se encarga de revisar si el usuario marcó la casilla de
“remember_me” para ser recordado en ese equipo, si la casilla fue marcada entonces se llama el
método “remember_token” y “remember_token_expires_at” que se encargan de asignar una fecha
en la que se debe dejar de recordar al usuario en ese equipo. El tiempo configurado es de 2 semanas,
52
sin embargo este parámetro es posible cambiarlo en el modelo “users.rb”.
Además se despliega un mensaje indicando que se ha conectado el usuario al sistema y envía
a la página de inicio del sistema, que se ha configurado como la lista de activos.
def destroy self.current_user.forget_me if logged_in? cookies.delete :auth_token reset_session flash[:notice] = "Se ha desconectado." redirect_back_or_default('/') end
El método de destruir llama a “forget_me” para evitar que el usuario siga siendo recordado
por el sistema en ese equipo. Además borra de la cache del sistema el identificador que permite
recordar al usuario. Luego despliega un mensaje indicando que el usuario ha sido desconectado del
sistema y redirecciona a la ruta raíz de la aplicación.
roles_controller.rb:
Este controlador se encarga de realizar la gestión de roles para los usuarios. Sus funciones
son las de crear y eliminar roles, desplegar los roles pertenecientes a un usuario y los roles que no
han sido asignados a este, de manera que el administrador pueda asignar estos roles a los usuarios.
layout 'application' before_filter :check_administrator_role
Inicialmente se define que los métodos de este controlador serán accesibles únicamente a el
o los usuarios administradores.
def index @user = User.find(params[:user_id]) @all_roles = Role.find(:all) end
El método de “listar” busca el usuario con el identificador especificado. Además busca todos
los roles existentes para luego mostrar la relación entre el usuario y los roles existentes en la vista.
Los métodos “mostrar”, “nuevo”, “crear” y “editar son idénticos a los descritos
anteriormente para el sistema de manejo de activos.
53
El método actualizar, permite asignar un rol a un usuario:
def update @user = User.find(params[:user_id]) @role = Role.find(params[:id]) unless @user.has_role?(@role.rolename) @user.roles << @role end redirect_to :action => 'index' end
El método anterior busca tanto el rol como el usuario y si este usuario no posee el rol se
procede a asignarlo y posteriormente redirecciona a listar de nuevo los roles para el usuario.
El método destruir realiza la operación inversa del método actualizar, ya que permite quitar
un rol a un usuario:
def destroy @user = User.find(params[:user_id]) @role = Role.find(params[:id]) if @user.has_role?(@role.rolename) @user.roles.delete(@role) end redirect_to :action => 'index' end end
Al igual que el método actualizar, este método busca el rol y el usuario y luego evalúa si el
usuario posee el rol para de ser así borrarlo de la lista de roles del usuario que se almacena en la
tabla de permisos.
accounts_controller.rb:
Este controlador se encarga únicamente de realizar la actualización de contraseñas de los
usuarios, ya que este proceso se realiza por aparte a la actualización del resto de los datos del
usuario. Debido a esto, el único método que posee es el de actualizar que se muestra a continuación:
def update return unless request.post? if User.authenticate(current_user.login, params[:old_password]) if ((params[:password] == params[:password_confirmation]) && !params[:password_confirmation].blank?) current_user.password_confirmation = params[:password_confirmation] current_user.password = params[:password] if current_user.save flash[:notice] = "Contraseña actualizada." redirect_to root_path #profile_url(current_user.login)
54
else flash[:error] = "Ocurrió un error, su contraseña no fue cambiada." render :action => 'edit' end else flash[:error] = "La nueva contraseña no coincide con la confirmación." @old_password = params[:old_password] render :action => 'edit' end else flash[:error] = "Su contraseña vieja es incorrecta." render :action => 'edit' end end
El método primero verifica que la contraseña vieja ingresada sea correcta. Luego revisa que
la contraseña nueva sea igual a la confirmación de esta y que no sea una contraseña en blanco, para
posteriormente salvar estas contraseñas para el usuario actual y desplegar una notificación
indicando que la contraseña fue actualizada.
Si no se puede guardar la contraseña se envía un mensaje de error indicando que no se pudo
actualizar esta y se regresa a la página de edición de la contraseña.
Luego, si la contraseña nueva asignada no coincidió con la confirmación de esta, o la
contraseña vieja ingresada no coincide con la almacenada para ese usuario, se despliega un mensaje
de error indicando cada caso.
55
CAPÍTULO 7: Vistas.
Las vistas corresponden a la parte de la aplicación encargada de realizar la interfaz gráfica
con el usuario. Al ser una aplicación web estas se realizan en códigos HTML, usando además llaves
especiales para añadir código en lenguaje Ruby embebido dentro del HTML.
Existen vistas para todos los controladores. Por ejemplo para activos existe una vista que
lista los archivos y es llamada por el método “listar” del controlador. De igual forma existen vistas
para los métodos “nuevo”, “mostrar” y “editar”.
En algunos casos no fue necesario todas estas vistas debido a que algunas de estas acciones
no estaban definidas en el controlador como se vio en el capítulo anterior.
7.1 Vistas del sistema de manejo de activos.
En este caso las vistas de activos son las más representativas pues estas tuvieron la mayor
cantidad de modificaciones. Debido a esto se explicará básicamente estas vistas aclarando que las
vistas para los modelos, marcas y estados son muy similares e inclusive más sencillas por lo que
sería repetitivo explicarlas.
Como es de suponerse la vista creada por defecto para “nuevo” y para “editar” son casi
idénticas, únicamente difieren en un par de textos. Debido a esto, para evitar realizar los cambios en
ambas vistas se utiliza un código genérico que es utilizado por las dos vistas. Este código se llama
parcial (partial) y se define iniciando el nombre del archivo con el símbolo “_”.
_form.html.erb:
#_form.html.erb <p> <%= f.label :num_serie %><br /> <%= f.text_field :num_serie %> </p> <p> <%= f.label :placa %><br /> <%= f.text_field :placa %> </p> <p> <%= f.label :modelo_id %><br /> <%= select("activo", "modelo_id", Modelo.find(:all).collect {|c| [c.nombre_modelo, c.id] }) %>
56
<%= link_to 'Crear modelo', new_modelo_path, :popup => true %></p> </p> <p> <%= f.label :estado_id %><br /> <%= select("activo", "estado_id", Estado.find(:all).collect {|c| [c.nombre, c.id] }) %> </p> <p> <%= f.submit label_text %> </p> <p><label
Este código se encarga de desplegar el formulario para creación y edición de los activos.
Primero despliega un campos de texto para ingresar el número de serie y de placa. Luego crea un
lista desplegable con la lista de los modelos existentes y de los estados respectivamente. Finalmente
se crean un botón para enviar los datos.
Cabe destacar que los códigos que se presentan entre las llaves “<%= %>”, corresponden a
códigos en lenguaje Ruby.
En los archivos “new.html.erb” y “edit.html.erb” se especifica que se utiliza el anterior
código y se pasa como variable el nombre del botón, ya que esta es la única diferencia entre las
páginas de “crear” y de “editar”.
new.html.erb:
<h1>Nuevo activo</h1> <% form_for(@activo) do |f| %> <%= f.error_messages %> <%= render :partial => "form", :locals => {:f => f, :label_text => "Crear"} %> <% end %> <%= link_to 'Atrás', activos_path %>
edit.html.erb:
<h1>Editar activo</h1> <% form_for(@activo) do |f| %> <%= f.error_messages %> <%= render :partial => "form", :locals => {:f => f, :label_text => "Actualizar"} %> <% end %> <%= link_to 'Ver', @activo %> | <%= link_to 'Atrás', activos_path %>
Podemos notar como la diferencia entre los dos códigos radica básicamente en el título de la
página y en el nombre del botón, que en un caso se pasa el parámetro “Crear” y en el de editar se
pasa el parámetro “Actualizar”. Además en el caso de “editar” se agrega un enlace a la página “ver”
57
para mostrar el contenido actual del estado que se esta editando.
El resultado de esto es una página como la que se muestra a continuación:
Figura 3. Vista para creación de activo.
Otra de las vistas corresponde a la de “mostrar” que se encarga de presentar en pantalla los
valores de las diferentes variables de un activo específico creado anteriormente.
show.html.erb:
<% form_tag({:controller => 'activos', :action => 'index'}, :method => 'get') do %> <%= text_field_tag "q", params[:q]|| '# de serie o placa '%> <%= submit_tag "Buscar!" %> <% end %>
El código anterior inicia creando un campo de texto para ingresar los parámetros de una
búsqueda. Este se crea como un forma que llama al método listar de el controlador de activos,
pasándole a este el parámetro de la búsqueda. Además se incluye un texto por defecto “# de serie o
placa” para indicar al usuario que esos son los parámetros que se utilizan para la búsqueda.
<p> <b>Num serie:</b> <%=h @activo.num_serie %> </p>
<p> <b>Placa:</b>
58
<%=h @activo.placa %> </p>
Ahora se muestra un encabezado para el número de serie y la placa del activo, desplegando luego el
valor de esa variable que se llama mediante la sentencia “@activo.placa”.
<p> <b>Modelo:</b> <%=h @activo.modelo.nombre_modelo %> </p>
<p> <b>Estado:</b> <%=h @activo.estado.nombre %> </p>
En el caso de el modelo y el estado para el activo, sabemos que en la tabla de activos se
almacena únicamente el número de identificación de estos, mediante una llave foránea. Por lo tanto
para lograr deplegar el nombre del modelo y de el activo es necesario realizar una llamada a las
herencias de ese activo como lo son “@activo.modelo” y “@activo.estado” y llamar ahora si al
nombre de cada uno de ellos para ser deplegado.
<% if current_user.has_role?('administrator') %>
<%= link_to 'Editar', edit_activo_path(@activo) %> | <%= link_to 'Atras', activos_path %>
<% end %>
Finalmente se evalúa si el usuario actual es administrador y en ese caso se despliegan los
enlaces para poder editar dicho activo y para volver a la página anterior.
El código despliega una página como la siguiente:
59
Figura 4. Vista para edición de activo.
La última vista para los activos corresponde a la de listar los activos. En esta se listan una
serie de activos según los parámetros que se hayan especificado. La lista puede ser para una marca
específica para un estado determinado o simplemente puede ser una lista de activos que
correspondan a un parámetro de búsqueda ingresado por el usuario.
Index.html.erb:
<% form_tag({:controller => 'activos', :action => 'index'}, :method => 'get') do %> <%= text_field_tag "q", params[:q]|| '# de serie o placa '%> <%= submit_tag "Buscar!" %> <% end %>
Inicialmente se crea un campo de texto para búsquedas igual al comentado en el caso de el
archivo de “mostrar”.
<% if params[:modelo_id].nil? and params[:estado_id].nil? %> <h1>Lista de activos</h1>
<% else if params[:modelo_id].nil? %> <h1>Lista de activos en estado "<%=h Estado.find(params[:estado_id]).nombre %>"</h1> <% else %>
<h1>Lista de activos para el modelo "<%=h Modelo.find(params[:modelo_id]).nombre_modelo%>"</h1> <% end %> <% end %>
El encabezado de la página puede variar dependiendo de el tipo de activos que se despliega
en la página, por lo tanto se realiza una lógica para determinar si existe algún parámetro de tipo de
modelo o de estado, para de esa manera especificar en la página que la lista de activos es para dicho
60
parámetro específico. Si no existen se despliega simplemente el mensaje “Lista de activos”.
<table border="1"> <tr> <th>Num serie</th> <th>Placa</th> <th>Modelo</th> <th>Descripción</th> <th>Estado</th> <th>Marca</th> </tr>
Se crea ahora una tabla y el nombre de sus columnas, para cada uno de los parámetros del
activo.
<% for activo in @activos %> <tr> <td><%= link_to activo.num_serie, activo %></td> <td><%=h activo.placa %></td> <td><%= link_to %Q{#{activo.modelo.nombre_modelo}}, {:action => 'index', :modelo_id => activo.modelo_id} %></td> <td><%= activo.modelo.descripcion %></td> <td><%= link_to %Q{#{activo.estado.nombre}}, {:action => 'index', :estado_id => activo.estado_id} %></td> <td><%= link_to %Q{#{activo.modelo.marca.nombre_marca}}, {:action => 'index', :marca_id => activo.modelo.marca_id} %></td> <% if current_user.has_role?('administrator') %>
<td><%= link_to 'Eliminar', activo, :confirm => '¿Está seguro que desea eliminar este elemento?', :method => :delete %></td> <% end %> </tr> <% end %> </table>
La lista se llena mediante una sentencia “for” de todos los activos encontrados para ese
parámetro.
Se agrega además un enlace al número de serie del activo de manera que al presionar sobre
este se despliegue la página donde se muestra dicho activo.
De igual manera se crea un enlace en el nombre del modelo y de el estado de manera que al
presionar sobre ellos se llama al método listar y se pasa como parámetro el identificador de ese
parámetro. Esto permite desplegar solamente los activos que pertenezcan al modelo seleccionado o
que tengan el estado seleccionado según sea el caso.
Se incluye además si el usuario es administrador un enlace para borrar cada activo, además
61
se agraga una confirmación de esta acción para evitar que se elimine un activo por error.
<%= will_paginate @activos %>
<br /> <% if current_user.has_role?('administrator') %>
<%= link_to 'Crear activo', {:action => 'new', :modelo_id => params[:modelo_id]} %> <% end %>
Finalmente se agrega una sentencia para indicar que se debe desplegar en varias páginas los
activos para evitar que se recargue mucho las páginas y realizar la búsqueda de un activo específico
de una manera más cómoda. Luego se verifica si el usuario es administrador y si es así se incluye un
enlace para crear un activo con el parámetro del modelo seleccionado en caso de existir.
Finalmente la página desplegada es la siguiente:
Figura 5. Vista de listado de activos.
7.2 Vistas del sistema de autenticación de usuarios.
Tenemos en esta sección las vistas para los controladores correspondientes a usuarios,
cuentas, roles, sesiones, y contraseñas.
Como se mencionó en el capítulo de controladores, algunos de los métodos comunes no
están presentes en muchos de los casos, debido a que no son necesarios o por seguridad no fueron
definidos.
62
Para los usuarios tenemos las vistas para crear, editar, listar y mostrar usuarios.
En el caso de listar se utilizó un parcial para separar el código, de manera que en este se
realice únicamente la parte que despliega los usuarios, mientras que el resto de la página se
completa en el siguiente archivo.
index.html.erb (users):
<% form_tag({:controller => 'users', :action => 'index'}, :method => 'get') do %> <%= text_field_tag "q", params[:q]|| 'Buscar Usuario '%> <%= submit_tag "Buscar!" %> <% end %>
Primero se agrega un cuadro de texto para ingresar parámetros de búsqueda, iguales a los
mencionados para el caso de los activos.
<h2>Lista de usuarios</h2> <table border="1"> <tr> <th>Usuario</th> <th>Nombre</th> <th>Apellido</th> <th>Carné</th> <th>Roles</th> </tr> <%= render :partial => 'user', :collection => @users %> </td>
Se crea una tabla con algunos de los parámetros de los usuarios. Luego se especifica que se
debe completar con el código del parcial “user”.
<%= link_to 'Crear_usuario', new_user_path %>
Se crea luego un enlace para permitir crear nuevos usuarios.
_user.html.erb:
<tr class="<%= cycle('odd', 'even') %>"> <td><%= link_to user.login, user_path(user) %></td> <td><%=h user.nombre %></td> <td><%=h user.apellido %></td> <td><%=h user.carne %></td> </td>
La tabla se completa con los datos de los usuarios como se muestra anteriormente. No todos
los datos son desplegados para evitar que la tabla se haga muy ancha e incómoda. Por lo tanto se
63
despliegan únicamente los datos más significativos. El resto de los datos se pueden observar
presionando sobre el enlace de el nombre de usuario el cual dirige hacia la página de “mostrar”
dicho usuario.
<% if user == current_user %> <td>Usuario actual</td> <%else%> <td><%= link_to 'Editar roles', user_roles_path(user) %></td> <td><%= link_to 'Eliminar', user, :confirm => '¿Esta seguro que desea eliminar el usuario?', :method => :delete %></td> <% end %> </tr>
Para finalizar la tabla se crean enlaces a editar roles y eliminar el usuario. Estos enlaces no
se despliegan en el caso del usuario actual porque sería un error grave eliminar o cambiar el rol a un
usuario administrador ya que perdería la capacidad de ingreso de nuevo al sistema o su cualidad de
administrador.
Esta vista se presenta a continuación:
Figura 6. Vista de listado de usuarios.
La vista “editar” permite editar los datos personales de el usuario, sin embargo el cambio de
contraseñas lo realiza otro controlador por lo tanto estos parámetros no se modifican en esta vista.
La vista “nuevo” y “mostrar” son muy similares a las mostradas anteriormente. En la vista
“nuevo” si se crea una forma para introducir todos los datos del usuario, incluyendo el nombre de
usuario en el sistema (login) y la contraseña la cual tiene un campo de confirmación para evitar
64
introducir un error en la contraseña.
El cambio de una contraseña lo realiza el controlador “accounts_controller.rb” por lo tanto
se tiene una vista separada para esto:
edit.html.erb(accounts):
<% form_tag url_for(:action => "update") do %> <p><label for="Contraseña anterior" class="block">Contraseña anterior</label><br /> <%= password_field_tag 'old_password', @old_password, :size => 45 %></p> <p><label for="Contraseña nueva" class="block">Contraseña nueva</label><br /> <%= password_field_tag 'password', {}, :size => 45 %><br /> <small>Entre 4 y 40 caracteres</small></p> <p><label for="Confirmacion de contraseña nueva" class="block">Confirmacion de contraseña nueva</label><br /> <%= password_field_tag 'password_confirmation', {}, :size => 45 %></p> <%= submit_tag 'Cambiar contraseña' %> <% end %>
Esta forma permite el cambio de contraseñas. Se despliega un cuadro te texto para la
contraseña vieja, luego se despliega uno para la contraseña nueva y otro para su confirmación.
Además se despliega un texto indicando al usuario que la contraseña debe estar entre 4 y 40
caracteres. Finalmente se coloca un botón para enviar los datos. La vista se presenta a continuación:
Figura 7. Vista de edición de contraseña.
Los roles son creados y destruidos únicamente desde el código fuente, por lo tanto no existe
vistas para crear ni editar estos. La única vista disponible para los roles es la de listar los roles, la
65
cual permite ver una lista de los roles para un usuario específico y añadir o quitar roles a este. Para
esto se utilizó por comodidad de programación un parcial llamado “_role.html.erb”.
_role.html.erb:
<li> <%= role.rolename %> <% if @user.has_role?(role.rolename) %> <%= link_to 'Remover rol', user_role_url(:id => role.id, :user_id => @user.id), :method => :delete %> <% else %> <%= link_to 'Agregar rol', user_role_url(:id => role.id, :user_id => @user.id), :method => :put %> <% end %> </li>
Este código verifica para cada código si este esta asignado al usuario, en cuyo caso se agrega
un enlace a “remover rol”, si el rol no esta asignado al usuario se incluye un enlace para agregar el
rol al usuario.
index.html.erb (roles):
<h2>Roles para <%=h @user.login.capitalize %></h2> <h3>Roles asignados:</h3> <ul><%= render :partial => 'role', :collection => @user.roles %></ul> <h3>Roles disponibles:</h3> <ul><%= render :partial => 'role', :collection => (@all_roles @user.roles) %></ul>
El código anterior muestra el nombre del usuario para el cual se estan desplegando los roles,
luego muestra por separado los roles asignados al usuario y los roles disponibles de la siguiente
manera:
Figura 8 . Vista de listado de roles asignados.
66
Figura 9. Vista de listado de roles no asignados.
La vista para crear una sesión corresponde a la forma de ingreso al sistema donde se le
solicita al usuario su nombre de usuario y su contraseña para poder conectarse al sistema.
El archivo presenta esta forma:
<center><h1>Introduzca su nombre de usuario y contraseña</h1><% form_tag session_path do %><p><label for="login">Usuario</label><br/><%= text_field_tag 'login' %></p>
<p><label for="password">Contraseña</label><br/><%= password_field_tag 'password' %></p>
<p><label for="remember_me">Remember me:</label><%= check_box_tag 'Recordarme en este equipo' %></p>
<p><%= submit_tag 'Entrar' %></center> <% end %>
Como podemos ver se muestra inicialmente un encabezado indicando que se debe ingresar el
nombre de usuario y la contraseña, Luego se agregan dos campos de texto para el nombre de
usuario y la contraseña.
67
Además se proporciona la opción de ser recordado en el equipo mediante una casilla de
verificación.
Finalmente se agrega un botón para enviar los datos e ingresar al sistema en caso de que sean
correctos.
7.3 Plantilla genérica para vistas.
Las vistas de los apartados anteriores sirven para desplegar los datos de la base de datos y
realizar cambios en esta. Otra parte de las vistas permite darle un aspecto más estético a la página,
mientras que proporciona algunos menús para movilizarse fácilmente entre páginas. Esta plantilla
permite crear encabezados a la página, así como barras laterales entre otras cosas.
La plantilla creada para el proyecto contiene un encabezado con el título del sistema y una
barra lateral donde se puede navegar a través de las diferentes páginas de la aplicación.
application.html.erb:
<title>Sistema de inventario EIE </title> <%= stylesheet_link_tag 'inventario' %> </head> <body id= "inventario">
El código anterior especifica el nombre que tendrá la página en la barra de título del
explorador web. Luego se especifica el nombre del archivo de hojas de estilos que se utilizará que
corresponde a “inventario.css”.
<div id= "banner">
<%= image_tag ("rails.png")%> <%= @page_title||"Inventario de Bodega EIE" %>
</div>
Se crea la primera división de la página. Esta corresponde a el encabezado de la página. En
este se agrega una imagen con el símbolo de el framework utilizado. Después se agrega un texto que
hará las de título de la aplicación. Se selecciono como título “Inventario de Bodega – EIE”. A esta
68
división se le da el identificador “banner”.
<div id="side">
<h1> Enlaces </h1> <% if logged_in? %>
<li><%= link_to 'Activos', activos_path %> <br /></li> <li><%= link_to 'Marcas', marcas_path %> <br /></li> <li><%= link_to 'Modelos', modelos_path %> <br /></li> <% if current_user.has_role?('administrator') %>
<li><%= link_to 'Estados', estados_path %> </li> <% end %> <br /><br />
<li>Logged in as:</li> (<%= link_to h(current_user.login.capitalize), user_path(current_user) %>)<br /><br /> <%= link_to 'Editar cuenta', edit_user_path(current_user) %><br /> <%= link_to 'Cambiar contraseña', change_password_path %><br /> <%= link_to 'Desconectarse', logout_url %><br />
<% if current_user.has_role?('administrator') %><br /> <li><%= link_to 'Administrar usuarios', users_path %></li>
<% end %> <% else %> <li><%= link_to 'Entrar', new_session_path %></li> <% end %> <br /> </div>
La segunda división corresponde a la barra lateral y es denominada “side”. Esta contiene el
menú que permite a los usuarios seleccionar las paginas deseadas.
Se evalúa si un usuario esta conectado. Si lo esta se despliega en el menú los enlaces para
ver activos, marcas y modelos. Si además el usuario es administrador se agrega el enlace de estados.
Luego se despliega el nombre del usuario conectado así como enlaces para editar cuenta,
cambiar contraseña y desconectarse del sistema. Una vez más si el usuario es administrador se
agrega la opción de administrar usuarios.
En el caso en que el usuario no este conectado al sistema simplemente se despliega un
enlace a “Entrar” que envía a la página de conexión al sistema.
<div id="main">
<% if flash[:notice] %>
<%= "<div class='notices'>" + flash[:notice] + "</div>" %> <% end %> <% if flash[:error] %>
69
<%= "<div class='error'>" + flash[:error] + "</div>" %> <% end %> <%= yield %> </div>
</div>
La última división de la página corresponde al espacio donde se despliegan las vistas para
todas las acciones y contenidos de la base de datos que fueron explicadas en los apartados
anteriores. Se indica primero un par de sentencias para que se desplieguen, en caso de existir,
mensajes de notificación o de error. Luego mediante la sentencia “<%= yield %> ” se indica que
se desplieguen la información de las otras vistas.
El último archivo que compone las vistas corresponde al archivo de hoja de estilos que
permite especificar el formato de cada una de las partes de la página. En este se especifican colores,
tipos de letra, tamaño de las divisiones de la página, alineaciones del texto entre otras cosas. Este
archivo se encuentra en la ruta “public/stylesheets” y es denominado “inventario.css”. La
explicación de el código de este archivo no se considera de importancia por lo que se omite.
A continuación se muestra la estructura de la página tanto para un usuario conectado como
para uno sin conectarse.
70
Figura 10. Vista final del sistema para un usuario conectado.
Figura 11. Vista final del sistema para un usuario desconectado.
71
CAPÍTULO 8: Traducciones.
Los mensajes de error que se presentan a la hora de realizar la validación de los datos son
mensajes genéricos desplegados por Ruby on Rails. Como se puede suponer estos mensajes están
por defecto en inglés, por lo que fue necesario realizar un “parche” para realizar la traducción de
estos mensajes. Se tradujo además la forma en la que se despliegan las fechas y tiempos restantes.
Para realizar esto se creó una carpeta llamada “overrides” en la cual se albergaron estos
archivos de traducciones que se comentan a continuación:
errors.rb
module ActiveRecord class Errors begin @@default_error_messages = { :inclusion => "no está incluido en la lista", :exclusion => "está reservado", :invalid => "no es válido", :confirmation => "no es una confirmación", :accepted => "debe ser aceptado", :empty => "no puede estar vacío", :blank => "no puede estar en blanco", :too_long => "es demasiado largo (máximo %d caracteres)", :too_short => "es demasiado corto (mínimo %d caracteres)", :wrong_length => "no tiene la longitud correcta (debería tener %d caracteres)", :taken => "ya existe en el sistema", :not_a_number => "debe ser un número" } end end end
El módulo anterior modifica la clase “errors” que se encarga de manejar los mensajes de
error para diferentes situaciones. Se puede observar como se presentan cambios en diferentes tipos
de error, como el caso de que un valor sea inválido, que no puede estar vacío o que la longitud no
esta en el rango permitido.
module ActionView #nodoc module Helpers module ActiveRecordHelper def error_messages_for(object_name, options = {}) options = options.symbolize_keys object = instance_variable_get("@#{object_name}") unless object.errors.empty?
72
content_tag("div", content_tag(options[:header_tag] || "h2", "Hay errores que impiden guardar el registro") + content_tag("p", "Compruebe los siguientes campos:") + content_tag("ul", object.errors.full_messages.collect { |msg| content_tag("li", msg) }), "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation" ) end end end end end
El módulo anterior se encarga de presentar los encabezados de los mensajes de error.
Cuando existen errores se despliegan los mensajes “Hay errores que impiden guardar en el registro”
y “Compruebe los siguientes campos”.
date.rb:
require 'date'
class Date remove_const(:MONTHNAMES) MONTHNAMES = [nil] + %w(Enero Febrero Marzo Abril Mayo Junio Julio Agosto Septiembre Octubre Noviembre Diciembre) remove_const(:ABBR_MONTHNAMES) ABBR_MONTHNAMES = [nil] + %w(Ene Feb Mar Abr May Jun Jul Ago Sep Oct Nov Dic) remove_const(:DAYNAMES) DAYNAMES = %w(Domingo Lunes Martes Miercoles Jueves Viernes Sábado) remove_const(:ABBR_DAYNAMES) ABBR_DAYNAMES = %w(Dom Lun Mar Mié Jue Vie Sáb) end
Este módulo realiza el cambio al español de los nombres de los meses y los días, además de
las abreviaciones de los días.
class Time alias :strftime_nolocale :strftime
def strftime(format) format = format.dup format.gsub!(/%a/, Date::ABBR_DAYNAMES[self.wday]) format.gsub!(/%A/, Date::DAYNAMES[self.wday]) format.gsub!(/%b/, Date::ABBR_MONTHNAMES[self.mon]) format.gsub!(/%B/, Date::MONTHNAMES[self.mon]) self.strftime_nolocale(format) end end
Este módulo cambia el formato de la fecha a un formato latino en el que se despliega
primero el día seguido por el més y el año.
module ActionView
73
module Helpers module DateHelper
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false) from_time = from_time.to_time if from_time.respond_to?(:to_time) to_time = to_time.to_time if to_time.respond_to?(:to_time) distance_in_minutes = (((to_time from_time).abs)/60).round distance_in_seconds = ((to_time from_time).abs).round
case distance_in_minutes when 0..1 return (distance_in_minutes == 0) ? 'menos de un minuto' : '1 minuto' unless include_seconds case distance_in_seconds when 0..4 then 'menos de 5 segundos' when 5..9 then 'menos de 10 segundos' when 10..19 then 'menos de 20 segundos' when 20..39 then 'medio minuto' when 40..59 then 'menos de un minuto' else '1 minuto' end
when 2..44 then "#{distance_in_minutes} minutos" when 45..89 then 'aprox. 1 hora' when 90..1439 then "aprox. #{(distance_in_minutes.to_f / 60.0).round} horas" when 1440..2879 then '1 día' when 2880..43199 then "#{(distance_in_minutes / 1440).round} días" when 43200..86399 then 'aprox. 1 mes' when 86400..525599 then "#{(distance_in_minutes / 43200).round} months" when 525600..1051199 then 'aprox. 1 año' else "over #{(distance_in_minutes / 525600).round} years" end end end end end
En este módulo se definen las expresiones para los casos de distancia de tiempo. Se definen
primero las distancias a partir de el número de segundos, desde 5 segundos hasta 1 minuto. Luego
se definen las distancias según los minutos, que van desde unos minutos hasta distancias de varios
años. Para esto se establecen algunos rangos en los que se considera cada condición, por ejemplo,
entre 45 minutos y 89 minutos se considera una distancia de aproximadamente 1 hora.
Finalmente estos archivos son incluidos en el archivo de configuración “environment.rb”.
De esta manera la aplicación sabe que debe cargar estos archivos a la hora de correr el servidor, de
manera que el “parche” quede funcionando.
74
CAPÍTULO 9: Pruebas.
Las pruebas realizadas al sistema consistieron básicamente en pruebas para comprobar la
integridad de los datos. Además se realizaron algunas pruebas para comprobar el funcionamiento
correcto de las búsquedas .
9.1 Pruebas de validación.
Las pruebas de validación se realizaron para comprobar el buen funcionamiento de la
validación de los datos. En el caso de los activos se especifico que la placa debía ser un valor único,
es decir que no puede estar registrada anteriormente en el sistema, esto evita que se ingresen al
sistema equipos que ya han sido registrados anteriormente por lo que se evita la duplicación de
datos.
Se intentó entonces introducir un valor de placa ya existente, teniendo el siguiente resultado.
Figura 12. Prueba de validación de placa existente.
Al intentar ingresar una placa ya existente el sistema lanza el mensaje de error indicando que
la placa ya existe, además se evita la creación del activo. Además se conservan los calores
ingresados por el usuario de manera que los pueda modificar fácilmente además de corroborar cual
fue el valor que produjo el error.
75
Otra prueba de validación realizada consiste en tratar de crear un activo con alguno de los
campos en blanco:
Figura 13. Prueba de validación de número de serie en blanco.
Figura 14. Prueba de validación de placa en blanco.
Como se observa se trato de dejar el número de serie y la placa en blanco. En ambos casos el
sistema notificó el error indicando la casilla que debe tener un valor.
La última prueba para los activos consiste en considerar un número de placa que contenga
caracteres diferentes a números. Esto debido a que se supone que los números de placa deben ser
estrictamente numéricos. La siguiente figura muestra el resultado:
76
Figura 15. Prueba de validación de placa no numeral.
Una vez más el sistema indica que existe un error en la placa ya que esta debe ser un número
y en la prueba se intentó ingresar un carácter.
En el caso de los usuarios las pruebas de validación fueron similares, obteniéndose
prácticamente los mismos resultados por lo que es repetitivo comentarlo.
9.2 Búsquedas.
Las búsquedas se habilitaron en el caso de los activos, los modelos , las marcas y los
usuarios. Se probó entonces el funcionamiento de estas en cada uno de los casos según el parámetro
de búsqueda especificado.
En el caso de los activos las búsquedas se pueden realizar por número de serie o por placa.
El resultado de ambos casos es el siguiente:
Figura 16. Prueba de búsqueda de activo por número de serie.
77
Figura 17. Prueba de búsqueda de activo por placa.
Se observa como los resultados coinciden con la búsqueda realizada en los dos casos.
Además se probó utilizando letras mayúsculas y minúsculas y se determino que las búsquedas no
son sensitivas a mayúsculas y minúsculas lo cual es satisfactorio ya que se desea que se detecten la
mayor cantidad de elementos con cada búsqueda, coincidentes con el parámetro.
Las pruebas de búsqueda realizadas para el caso de las marcas, modelos y usuarios tuvieron
resultados similares, por lo que fueron muy satisfactorias.
78
CAPÍTULO 10: Conclusiones y recomendaciones.
10.1 Conclusiones.
● El desarrollo de aplicaciones con una herramienta como Ruby on Rails es sencillo debido a
que evita al programador tener que programar cosas que ya han sido desarrolladas,
permitiendo a este concentrarse realmente en las partes que son esenciales según los
requerimientos de la aplicación que debe desarrollar.
● El patrón modelovistacontrolador permite un mayor orden y una independencia entre las
partes de la aplicación, brindando a cada una de ellas una función especifica diferente a las
funciones de las otras partes del programa. Además permite que el entendimiento del código
sea más sencillo.
● Un sistema computarizado de base de datos para almacenar activos de bodega permite un
manejo confiable de la información, además facilita realizar cambios en el inventario, de
manera que se puede considerar como una gran mejora con respecto a inventarios
almacenados en papel.
● Las pruebas realizadas al sistema fueron satisfactorias por lo que se puede confiar en el
funcionamiento correcto del sistema. La validación de los datos es la correcta, y puede ser
modificada según las directivas deseadas por el encargado de bodega que va a utilizar el
sistema.
● El sistema desarrollado cumple con todas las especificaciones y requerimientos que fueron
solicitados por lo que se puede utilizar para sustituir el sistema actual de almacenamiento de
información de inventario de la bodega de la Escuela de Ingeniería Eléctrica de la
Universidad de Costa Rica.
79
10.2 Recomendaciones.
● Se podría agregar al sistema una sección para manejo de componentes electrónicos
existentes en bodega, de manera que los estudiantes puedan ingresar al sistema y revisar los
elementos que tienen disponibles para realizar sus laboratorios. Estos elementos como
resistencias, condensadores, integrados, etc se deben manejar en tablas diferentes, ya que no
poseen los mismos atributos que los equipos y es muy difícil llevar control de la cantidad
existente, sino únicamente de su existencia en la bodega.
● El sistema puede completarse con un sistema de manejo de préstamos a los estudiantes, que
permita a un estudiante reservar equipos de forma remota y al administrador llevar un
registro digital de los prestamos que se han realizado. Para esto se puede crear una tabla que
contenga la relación entre los usuarios y los equipos que han sido prestados a estos. La
modificación de la base de datos se puede realizar fácilmente mediante migraciones de
manera que se mantenga la información existente en ella.
80
BIBLIOGRAFÍA:
[1] Korth H. F. , “Fundamentos de bases de datos”, Segunda edicion, McGrawHill /
Interamericana de España S. A. , México, 1993.
[2] Wikipedia. “Base de Datos”, Wikipedia,
http://es.wikipedia.org/wiki/Base_de_datos
[3] Wikipedia. “Sistemas Gestores de Base de Datos”, Wikipedia,
http://es.wikipedia.org/wiki/Sistemas_gestores_de_bases_de_datos, Setiembre, 2008.
[4] Wise, B. “Normalización de bases de datos y técnicas de diseño”,
http://www.bulma.net/body.phtml?nIdNoticia=483, 2001.
[5] Wikipedia. “Ruby”, Wikipedia,
http://es.wikipedia.org/wiki/Ruby, Setiembre, 2008.
[6] Wikipedia. “Ruby on Rails” Wikipedia,
http://es.wikipedia.org/wiki/Ruby_on_Rails, Setiembre, 2008.
[7] “Ruby Tutorial”, http://rubytutorial.wikidot.com/introduccion, Junio, 2008.
[8] “Manual del Usuario de PostgreSQL”,
http://es.tldp.org/Postgresqles/web/navegable/user/user.html
[9] Wikipedia. “ModeloVistaControlador” ,Wikipedia,
http://es.wikipedia.org/wiki/Modelo_Vista_Controlador, Setiembre, 2008.
[10] ”Patrón “Modelocontroladorvista”,
http://www.proactivacalidad.com/java/patrones/mvc.html, Octubre, 2008.
[11] Jesús Dugarte “Rails en español”,
http://jdugarte.blogspot.com/2008/04/railsenespaol.html, Abril, 2008.
81
Recommended