|
Hola a todos los que visitan estos documentos... Pues bien aqui me tienen con otro ejercicio en ruby on rails ahora tratando de resolver un pequeño problema... Pasemos al problema Bien lo que quiero hacer aqui es una relacion n:n de dos tablas... Veamos el problema Tengo una tabla con alumnos y a cada alumno le quiero asignar uno o mas grupos y en la misma proporcion uno grupos puede estar asignado a uno o mas alumnos.... Pues manos a la obra Primero debemos crear nuestra base de datos, en este caso yo la llame escuela fvasquez@inf:~$ sudo mysqladmin create escuela Y vamos a crear la tabla de usuarios en este caso solamente vamos a crear el indice y un campo que sera para el nombre del alumno CREATE TABLE `usuarios` ( `id` int(11) NOT NULL auto_increment, `nombre` varchar(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; Tambien vamos a crear la tabla de grupos y le vamos a ingresar directamente unos valores, como estos valores quiza no se alteren no necesitaremos tener un metodo de captura para esta tabla asi que desde este momento le asignaremos valores a la tabla. CREATE TABLE `grupos` ( `id` int(11) NOT NULL auto_increment, `nombre` varchar(30) NOT NULL, `valor` varchar(2) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; INSERT INTO `grupos` (`id`, `nombre`, `valor`) VALUES (1, 'primero', '01'), (2, 'segundo', '02'), (3, 'tercero', '03'), (4, 'cuarto', '04'), (5, 'Quinto', '05'), (6, 'Sexto', '06'); Y aqui viene lo bueno.......... Ahora debemos cumplir la relacion n:n a nivel de base de datos para lo cual construimos una tercera tabla la cual nos servira de enlace entre las dos anteriores, y la cual contendra los indices de usuarios y grupos CREATE TABLE `grupos_usuarios` ( `usuario_id` int(11) NOT NULL, `grupo_id` int(11) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; Bien ya tenemos nuestras tablas, ahora si a trabajar en el entorno de ruby on rails fvasquez@inf:~$ rails escuela Con esto tenemos construida la estructura para nuestro proyecto Ahora a editar Editamos el archivo config/database.yml y lo dejamos como se muestra a continuacion fvasquez@inf:~/escuela$ nano config/database.yml development: adapter: mysql database: escuela username: root password: socket: /var/run/mysqld/mysqld.sock # Warning: The database defined as 'test' will be erased and # re-generated from your development database when you run 'rake'. # Do not set this db to the same as development or production. test: adapter: mysql database: escuela username: root password: socket: /var/run/mysqld/mysqld.sock production: adapter: mysql database: escuela username: root password: socket: /var/run/mysqld/mysqld.sock Ahora tenemos el enlace a nuestra base de datos, con esto ya podemos ayudarnos de scaffold para construir el CRUD de nuestras tablas... Vamos a crear el templete para la tabla de usuarios, scaffold nos creara el controlador, el modelo, las vistas y otras cosas mas que necesitamos... fvasquez@inf:~/escuela$ ruby script/generate scaffold Usuario Vamos a prender nuestro servidor mongrel y vemos en el navegador que tenemos.... fvasquez@inf:~/escuela$ ruby script/server mongrel -d Y nos vamos al navegador localhost:3000/usuarios/ Y tenemos un programa funcional donde podemos agregar, eliminar, editar, mostrar, listar el contenido de la tabla usuario. Vamos con los grupos ... El objetivo es mostrar al mismo tiempo un campo de la tabla grupos desplegado en check_box's y de esa manera hacer mas facil al usuario la seleccion.. Ahora vamos a trabajar con la tabla de grupos como la tabla grupos ya tiene valores que le asignamos en el momento de la creacion de la tabla, y estos valores van constantes entonces para esta tabla solo vamos a crear su modelo... fvasquez@inf:~/escuela$ ruby script/generate model Grupo Ya tenemos los modelos de las tablas usuarios y grupos, ahora podemos indicar la relacion n:n a nivel programacion Editamos los modelos y los dejamos como se muestra a continuacion fvasquez@inf:~/escuela$ nano /app/models/usuario.rb class Usuario < ActiveRecord::Base has_and_belongs_to_many :grupos end fvasquez@inf:~/escuela$ nano /app/models/grupo.rb class Grupo < ActiveRecord::Base has_and_belongs_to_many :usuarios end Con esto le queremos decir que un usuario tiene y pertenece a muchos grupos y un grupo tiene y pernetenece a muchos usuarios, con esto cumplimos la relacion n:n Ahora vamos a modificar la vista de nuestro usuario para integrarle los campos de la tabla de grupos y poder asignar valores en ambas tablas en una misma forma fvasquez@inf:~/escuela$ nano app/views/usuarios/_form.rhtml y lo dejamos como se muestra a continuacion <%= error_messages_for 'usuario' %> <!--[form:usuario]--> <p><label for="usuario_nombre">Nombre</label><br/> <%= text_field 'usuario', 'nombre' %></p> <% for g in Grupo.find(:all) %> <div> <%= check_box_tag "usuario[grupo_ids][]", g.id ,@usuario.grupos.include?(g) <%= g.nombre %> </div> <% end %> <!--[eoform:usuario]--> Lo que hicimos aqui es un ciclo asignandole al objeto g todos los elementos del objeto Grupo y crear un chek_box_tag se ayude del arreglo grupo_ids para almacenar los elementos que se seleccionen tomando el valor del campo id del objeto g, y va a relacionarlos en la tabla grupos_usuarios El metodo create y el update de nuestro proyecto utilizan el mismo principio asi que vamos a ver como funcionan ambos... Al parecer el metodo update cuando eliminamos elementos de la lista nos mantiene los mismos y no se actualizan como deberia asi que vamos a nuestro controlador a modificar el metodo edit. def update params[:usuario][:grupo_ids] ||= [] @usuario = Usuario.find(params[:id]) if @usuario.update_attributes(params[:usuario]) flash[:notice] = 'Usuario was successfully updated.' redirect_to :action => 'show', :id => @usuario else render :action => 'edit' end end Si nos damos cuenta solo ingresamos esta linea params[:usuario][:grupo_ids] ||= [] Esto quiere decir que el parametro grupo.ids del objeto Usuario.update se va a evaluar contra un arreglo vacio a traves de un OR y si el valor de la izquierda es nulo (.nil) etonces se nos devolvera el valor de la derecha que en este caso es un arreglo vacio.. Bien solo falta mostrar la lista de todos los usuarios y por cada uno de ellos que grupos que tienen asignados... A editar nuevamente y dejamos el archivo como se muestra a continuacion fvasquez@inf:~/escuela$ nano app/views/usuarios/list.rhtml <h1>Listing usuarios</h1> <table> <tr> <% for column in Usuario.content_columns %> <th><%= column.human_name %></th> <% end %> </tr> <% for usuario in @usuarios %> <tr> <% for column in Usuario.content_columns %> <td><%=h usuario.send(column.name) %></td> <%for g in usuario.grupos%> <ul> <td><%=h g.nombre %></td> </ul> <%end%> </tr> <% end %> <tr> <td><%= link_to 'Show', :action => 'show', :id => usuario %></td> <td><%= link_to 'Edit', :action => 'edit', :id => usuario %></td> <td><%= link_to 'Destroy', { :action => 'destroy', :id => usuario }, :confirm => 'Are you sure?', :method => :post %></td> </tr> <tr> <td>_</td> </tr> <% end %> </table> <%= link_to 'Previous page', { :page => @usuario_pages.current.previous } if @usuario_pages.current.previous %> <%= link_to 'Next page', { :page => @usuario_pages.current.next } if @usuario_pages.current.next %> <br /> <%= link_to 'New usuario', :action => 'new' %> Lo que agregamos fue esto que es un ciclo que esta dentro de cada usuario para mostrar el campo nombre de la tabla grupos basandose en la relacion n:n que se hizo con la tabla grupos_usuarios <%for g in usuario.grupos%> <ul> <td><%=h g.nombre %></td> </ul> <%end%> Bueno aqui les dejo esto... Cualquier sugerencia o critica es bienvenida Faustino Vasquez Limon Universidad Xochicalco Campus Tijuana Linux User: "Agrega Espacio a Tu Disco Duro Quitando Windows"
|