COMO Aplic. RoR con check_boxs para una relacion N:N

0
424

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’ %>

Nombre

<%= text_field ‘usuario’, ‘nombre’ %>

<% for g in Grupo.find(:all) %>

<%= check_box_tag “usuario[grupo_ids][]”, g.id ,@usuario.grupos.include?(g)
<%= g.nombre %>

<% end %>


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

Listing usuarios

<% for column in Usuario.content_columns %>

<% end %>

<% for usuario in @usuarios %>

<% for column in Usuario.content_columns %>

<%for g in usuario.grupos%>

    <%end%>

    <% end %>

    <% end %>

    <%= column.human_name %>
    <%=h usuario.send(column.name) %><%=h g.nombre %>
    <%= link_to ‘Show’, :action => ‘show’, :id => usuario %><%= link_to ‘Edit’, :action => ‘edit’, :id => usuario %><%= link_to ‘Destroy’, { :action => ‘destroy’, :id => usuario }, :confirm => ‘Are you sure?’, :method => :post %>
    _

    <%= 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 %>

    <%= 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%>

      <%=h g.nombre %>

    <%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”

     

    LEAVE A REPLY

    Please enter your comment!
    Please enter your name here