Definir modelo de tablas un poco "feas"

Hola, estoy tratando de definir correctamente (o sea, elegantemente)
un modelo (o modelos) para los datos de dos tablas cuya estructura,
aunque simple, no es muy agracedida.

Las tablas son “usuarios” y “grupos”:

usuarios

  • id
  • username
  • domain
  • more_data
    (username + domain es UNIQUE)

grupos

  • id
  • username
  • domain
  • group

Como veis no hay relación entre tablas, y encima cada entrada en la
tabla “groups” NO es un grupo único, si no un grupo perteneciente a
dicho username@domain. Es decir, para decir que un usuario
[email protected]” pertenece a los grupos GRUPO_A y GRUPO_B habría que
crear 2 entradas en la tabla “groups”:

id username domain group

1 pepe dominio.com GRUPO_A
2 pepe dominio.com GRUPO_B

Intento entonces crear un atributo “grupos” en el modelo de “Usuario”
que me devuelva un Array con los nombres de los grupos a los que
pertenece. Para ello he creado un modelo “Grupo” que accede a su tabla
“grupos”.

Hasta ahora sólo se me ocurre definir esto en el modelo “Usuario”:

def grupos()
grupos = Grupo.find(:all, :conditions => { :username =>
self.username, :domain => self.domain })
grupos.“posible marranada para extraer sólo los nombres de grupo a un
array”
end

Lo que pasa es que eso no me devuelve un Array con nombres de grupo,
sino un Array con objetos de tipo “Grupo” y tendría que hacer alguna
“marranada” para desde ahí crear el array que busco.

Dudas:

  • ¿Debo hacer esa “marranada”?
  • ¿Hay alguna otra forma de definir el modelo o la relación entre
    modelos para conseguir esto más elegantemente? (obviamente no me sirve
    “has_many :grupos” ya que ni existe clave foránea y encima es una
    clave compuesta “username+domain”).

Gracias por cualquier sugerencia. Saludos.

El 20/02/08, Iñaki Baz C. [email protected] escribió:

Lo que pasa es que eso no me devuelve un Array con nombres de grupo,
sino un Array con objetos de tipo “Grupo” y tendría que hacer alguna
“marranada” para desde ahí crear el array que busco.

Dudas:

  • ¿Debo hacer esa “marranada”?

Finalmente he hecho dicha “marranada” que ha resultado no serlo tanto:

def grupos()
grp_entries = Grupo.find(:all, :conditions => { :username =>
self.username, :domain => self.domain })
grupos = Array.new
grp_entries.each {|grp_entry| grupos.push(grp_entry.name)}
grupos
end

¿Se os ocurre algo más elegante o tiro con esto? :slight_smile:

Hola,

sin saber mucho me parece que esto es un clasico :has_many

Usuario
:has_many :grupos
:Aqui_va_la_restricción_de_unicidad_para_los_campos username+domain

Grupo
:belongs_to :usuario

y las tablas te quedarían asi

Usuario (id, username, domain, other_data)
Grupo (id, usuario_id, grupo)

puedes prescindir en la tabla Grupo de los campos username y domain, ya
que al poner la restricción en la tabla Usuario de unicidad a
username+domain solo te basta con el id de Usuario para identificarlo
“unequivocamente” (si es que existe esa palabra :D).

Con esto puedes usar los clásicos find para acceder a los grupos de un
usuario.

Me corrigen si me equivoco.

Saludos

Sergio
La Serena
Chile.

Iñaki Baz C. escribió:

On 20/02/2008, Iñaki Baz C. [email protected] wrote:

¿Se os ocurre algo más elegante o tiro con esto? :slight_smile:

Esto que has hecho se puede solucionar así

grupos = Grupo.find(:all, :conditions => { :username =>self.username,
:domain => self.domain }, :select => ‘grupo’)
nombres_grupos = grupos.collect(&:grupo)

Pero no entiendo si el modelo de datos lo has hecho tú o es legacy y
tienes que tirar con él. Si puedes cambiarlo, lo normal es que tengas
una tabla User con los datos de usuario, una Grupos con los datos del
grupo y, o bien una tabla de cruce y un relación habtm o, para mi
mejor, un modelo Pertenencia que te sirva para relacionar Grupos y
Ususarios mediante un has_many :through


Manuel, que
piensa que eres una excelente persona y medra en torno a
http://simplelogica.net y/o http://simplelogica.net/logicola/
Recuerda comer mucha fruta y verdura.

Hola,
¿Porque no puedes hacer has_many: grupos? ¿No puedes modificar las
tablas?

Me parece que es una relación muchos a muchos (ya que un usuario puede
estar
en varios grupos) y necesitas una tabla intermedia “grupos_usuarios”,
con
este nombre, para que Rails la reconozca sin problemas (nombres en orden
alfabético)

class Usuario
has_and_belongs_to_many :grupos

class Grupo
has_and_belongs_to_many :usuarios

y la tabla intermedia

grupos_usuarios (
grupo_id
usuario_id
)

y naturalmente eliminas de la tabla grupos los atributos username y
domain.
Puedes mantener el unique de usuarios, si es que un usuairo pertenece a
un
sólo dominio, si no es así haría una tabla Dominios.

Creo que mejor modificas las tablas, más que “parchar”, si no, más
adelante
tendras más problemas.


Saludos
Atte.
Jean Marcel Droguett.

El día 20/02/08, Iñaki Baz C. [email protected] escribió:

El 20/02/08, Manuel González Noriega
[email protected] escribió:

grupos
nombres_grupos = grupos.collect(&:grupo)
Qué buena !! No había visto el parámetro “select” :wink:

Pero no entiendo si el modelo de datos lo has hecho tú o es legacy y
tienes que tirar con él. Si puedes cambiarlo, lo normal es que tengas
una tabla User con los datos de usuario, una Grupos con los datos del
grupo y, o bien una tabla de cruce y un relación habtm o, para mi
mejor, un modelo Pertenencia que te sirva para relacionar Grupos y
Ususarios mediante un has_many :through

Lo sé, pero las tablas vienen así de fábrica y no se pueden cambiar :frowning:

Muchas gracias.

El 20/02/08, Jean D. [email protected] escribió:

Hola,
¿Porque no puedes hacer has_many: grupos? ¿No puedes modificar las tablas?

Gracias, pero no puedo modificar las tablas en absoluto, las usa otra
aplicación y deben ser así.

No obstante ya lo he dejado bastante bonito con la sugerencia de
Manuel Gonzalez.

Saludos.