Obtener datos en una relación n a n

Hola, verán, ando un poco pez y liado con las relaciones “n a n” a la
hora de obtener los datos

class Usuario < ActiveRecord::Base
has_many :pertenencias
has_many :grupos, :through => :pertenencias
end

class Pertenencia < ActiveRecord::Base
belongs_to :usuario
belongs_to :grupo
end

class Grupo < ActiveRecord::Base
has_many :pertenencias
has_many :usuarios, :through => :pertenencias
end

En este ejemplo tengo claro que si hago un find a Pertenencia

p = Pertenencia.find( :all )

Puedo llegar a obtener los datos de usuarios (p.usuario) ó grupos
(p.grupo)

lo que no consigo es obtener los datos de la tabla Grupos pero
haciendo el find a usuarios (u = Usuarios.find(:all) para luego hacer
algo como u.pertenencias )
e usado las opciones include y join pero no hay manera.

No se si me habré explicado bien.

Muchas gracias por la ayuda.

Saludos.

On 9/17/07, alarkspur [email protected] wrote:

class Pertenencia < ActiveRecord::Base

p = Pertenencia.find( :all )

Puedo llegar a obtener los datos de usuarios (p.usuario) ó grupos (p.grupo)

lo que no consigo es obtener los datos de la tabla Grupos pero haciendo el
find a usuarios (u = Usuarios.find(:all) para luego hacer algo como
u.pertenencias )
e usado las opciones include y join pero no hay manera.

No se si me habré explicado bien.

Creo que no te entiendo, podrías explicarlo de otra manera?
Quizás"quiero traer todos los usuarios con sus respectivos grupos", en cuyo
caso:

Usuario.find(:all, :include => :grupos).each do |usuario|
puts “Usuario: #{usuario} pertenece a los grupos
#{usuario.grupos.to_sentence}”
end

Es exactamente lo que yo tengo planteado en mi aplicación, solo que yo
no
sabá aun el detalle del :through. En mi caso tengo un atributo isadmin
en la
tabla Pertenencias (en mi caso se llama distinto).

Yo por mi parte tengo la duda de que veo que el Rails te genera lo
siguiente
(mas o menos) en los metodos list del controlador

def list
@usuarios, @pagina = paginate :usuarios , :page_size => 10
end

Yo me pregunto:

el simbolo :usuarios ¿de donde sale? ¿hay una lista predefinida o quizá
:usuarios es un simbolo con el sql para obtenerlo todo por defecto?
He visto que hay un paginate_by_sql. ¿se puede aplicar un filtro a una
lista
predefinida o tengo que hacer una sentencia sql nueva?
O mejor. ¿como podría paginar una lista obtenida con find, find_by_*
etc.?

un saludo
Rafa

On 9/18/07, Rafa C. [email protected] wrote:

He visto que hay un paginate_by_sql. ¿se puede aplicar un filtro a una lista
predefinida o tengo que hacer una sentencia sql nueva?
O mejor. ¿como podría paginar una lista obtenida con find, find_by_* etc.?

El símbolo :usuarios no es más que una cadena inmutable. En este caso,
Rails puede conocer el nombre de tu modelo de datos mediante el
símbolo:

:usuarios.to_s
=> “usuarios”

:usuarios.to_s.classify
=> “Usuario”

:usuarios.to_s.classify.constantize
=> Usuario

:usuarios.to_s.classify.constantize.new
=> #<Usuario:0xb765e5c0 @new_record=true, @attributes={}>

Sobre la paginación, podrías usar will_paginate [1], ya que la
paginación de Rails parece haber quedado obsoleta.

[1] http://errtheblog.com/post/4791

lo que trato es traerme todos los usuarios, incluso los que no
pertenecen a ningún grupo.

he realizado una forma un tanto “chapuzera” ya que realizo tantas
consultas a la base de datos como usuarios tengo.

controlador

@usuarios = Usuario.find( :all )

vista

@usuarios.each do |u|
#{u.name} pertenece a #{ dime_grupo( u.id ).grupo.name }
end

#helper
def dime_grupo( record )
Pertenencia.find( :all, :conditions => [ “user_id = ?”, record ] )
end

Como veis es una forma un poco (bastante) chapuzera, ya que debería
traerme todos los registros de una sola vez, pero si hago algo como
@usuarios = Usuario.find( :all, :include => :grupos )

me lanza el error
uninitialized constant Usuario::Pertenencia

On 9/18/07, alarkspur [email protected] wrote:

lo que trato es traerme todos los usuarios, incluso los que no
pertenecen a ningún grupo.

Como te decía:

Usuario.find(:all, :include => :grupos).each do |usuario|
puts “Usuario: #{usuario} pertenece a los grupos
#{usuario.grupos.to_sentence}”
end

Detrás de escena esto hace un par de LEFT JOINs, por lo cual
deberíatraerte todos los usuarios (y es lo que la sintaxis sugiere).

Yo soy mas partidario de hacer solo la consulta de pertenencias y en la
vista traerme el usuario o el grupo. Eso si, esto solo vale si la vista
está
paginada, ya que así ahorras joins innecesarios a la base de datos
(aunque
hagas mas peticiones). Si vas a mostrarlos todos pues entonces hazlo con
jion, que será mas rápido y solo harás una petición.

Vale, ¿entonces el metodo seria construir mis listas de resultados y
despues
aplicarles la paginación?
(no conozco aun ese will_paginate ¿es una Gema, un plugin?)

Ya encontré el fallo :slight_smile:

El fallo estaba en que en un ejemplo la tabla intermedia entre grupos
y usuarios la había llamado pertenencias y funcionaba perfectamente
tal y como había indicado Damian.

En otro ejemplo a la tabla intermedia la había llamado
grupos_usuarios y genera el error precisamente por el _ ya que si a
la tabla la llamo gruposusuarios si que funciona.
Vaya desconocía este problema con los nombres.

Siempre había visto en todos los ejemplos que a las tablas
intermedias se las asignaba los nombres según las 2 tablas de las que
provenían, en orden alfabético y usando el _
¿no es esto correcto? o lo que hay que hacer es pasar del
guión.
Gracias por las aclaraciones.
Un saludo.

Gracias Damian, si el caso es que seguí tu forma y lo realice como me
indicaste pero me lanza el error
uninitialized constant Usuario::Pertenencia

Sabiendo que como indicas es la forma correcta revisare el resto del
código a ver el por que del fallo.

Muchas gracias.
Un saludo.