Bienvenido a   :: LINUX SOLUTIONS CENTER ::

México,  Viernes 21 de Noviembre del 2008   
  Hora Local
Home Programacion COMO Aplic. RoR con check_boxs para una relacion N:N
LINUX es nuestra Especialidad: · Servidores de Internet · Monitoreo de Servidores y Enlaces · Virtualizacion · Firewalls con OpenSource · Proxy Servers (Web Cache) · DNS y DHCP · Web Server · Webmail · NAT's · IP Forwarding · FTP Server · Email Attachmnt Filtering · Reportes estadisticos · Linux Gateway/Router · Bloqueo de Puertos · Email Server · Reporte de todo el trafico interno/externo · Administracion de Ancho de banda · VPN's con Open VPN · Soporte Ténico comercial · Administración de servidores Linux (RedHat EL/AS, Debian, CentOs, etc) · Instalación y Configuración de Servidores · Configuración de servidores de E-Mail (Sendmail, Qmail, Postfix con virtual domains) · Antvirus con OpenSource · Administración de LVM · y mas... mucho mas
Linux Solutions C.
Acerca de
Actualidad
GNU/Linux
Gente en Línea
Tenemos 48 invitados conectado
Estadísticas
Ver contenido por hits : 192293
Acceso



Google Translation

 
Temas Relacionados

GULEV | Software Libre


Banner Advertisement
COMO Aplic. RoR con check_boxs para una relacion N:N PDF Imprimir E-mail
Programacion Unix-Linux
Escrito por Fvasquez   
Sábado, 02 de Febrero de 2008 20:37

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"

 

Actualizado ( Miércoles, 05 de Marzo de 2008 21:06 )
 


LSC Support Online
SysOp
Tech Support
Encuestas
¿Cuál es tu navegador favorito?
 
Anunciate aquí

Centro de Soluciones Linux

KoalaSoft-Sitio de Amigos

ODM SYSTEM MEXICO

No. de Visitas
mod_vvisit_countermod_vvisit_countermod_vvisit_countermod_vvisit_countermod_vvisit_countermod_vvisit_counter
mod_vvisit_counterHoy457
mod_vvisit_counterAyer636
mod_vvisit_counterEsta Semana2604
mod_vvisit_counterEste Mes9242
mod_vvisit_counterTotal76948
Linuxsc en RSS
Archivo Historico

Ultimo Reporte