2010/4/7 Lean <[email protected]> > Hola gente, > > Después de un tiempo como "voyeur", voy a hacer mis primera consulta al > grupo. Creo que es una tontería de principiante, y la verdad es que quería > iniciarme en una consulta de mayor nivel ;-( pero bueno, aquí voy... Pido > disculpas por lo largo del mail. >
¡bienvenido! > Tengo dos tablas, "clientes" y "hosts", mapeadas a través de ActiveRecord a > clases Cliente y Host, según una relación "Cliente <1:n> Host". > asegurate de que las clases estén correctamente mapeadas... esto es, en Cliente debería haber una sentencia "has_many :hosts" y en Host "belongs_to :cliente" (para la memoria: belongs_to va del lado de la FK). Sugerencia: acostumbrate a que todo tu código esté en un sólo idioma, no mezcles inglés y español (como difícilmente logres tener TODO en español, esto significa que deberías acostumbrarte a codear en inglés lamentablemente -- en cualquier momento lanzamos "Rieles" :P). > Utilizando un find convencional con joins y select, hago: > > @hosts = Host.find(:all, :joins => "as h inner join clientes as c on > c.id=h.cliente_id, > :select => "h.*, c.nombre") > > Lo que obtengo es la lista de hosts que cumplen con el join, pero no me > está incluyendo el "c.nombre", cosa que necesito. > El problema con esto es conceptual: estás utilizando Host para algo de Cliente. Olvidate de que estás trabajando con SQL, trabajá con tus entidades. Si están bien mapeadas, sólo necesitás hacer esto: @hosts = Host.all # esto es un shortcut, simil Host.find :all nombre_primer_cliente = @hosts.first.cliente.nombre > Por otro lado, una consulta como esta, sin el :select me da error: > > @hosts = Host.find(:all, :joins => "as h inner join clientes as c on c.id > =h.cliente_id") > > ActiveRecord::StatementInvalid: Mysql::Error: Unknown table 'hosts': SELECT > `hosts`.* FROM `hosts` as h inner join clientes as c on h.cliente_id=c.id > > > Entiendo que el error me lo dá la base de datos, puesto que no le gusta el > SELECT "*`hosts`.**". > > Una expresión con un :joins de la siguiente manera, no me da error, pero > tampoco me da las columnas de la otra tabla... > > @hosts = Host.find(:all, :joins => [:cliente]) > Una sugerencia: dejá SQL (o "partes" de SQL), selects, joins, includes, etc, para los casos complejos. Olvidate de que estás trabajando con una base de datos SQL. * :select no deberías usarlo jamás (sólo que realmente te encuentres que te reporte un beneficio REAL de performance, son casos MUY aislados) * :joins... tampoco (al menos hasta que salga Rails 3 que parece que sabe mapearlo mejor) * :include usalo como una optimización de performance nada más; tomando el caso de los @hosts, imaginate un @hosts.each do |host| puts host.cliente.nombre end, siendo @hosts como lo obtuve yo más arriba, eso genera muchos queries SQL innecesarios, con :include podés evitar eso nada más (googlealo hay buena info al respecto) > Tal vez entendí mal, pero esto debería funcionar dandome no sólo los campos > de host, sino tambien los de las tablas incluídas en :joins, no es así? > No. Con select podés forzarlo a que te aparezcan, por ejemplo, campos de Cliente en Host. Esto está realmente mal, te lo dice alguien que heredó código que hacía eso y se volvió loco. Usá ActiveRecord, para eso está. @host.cliente es mucho más obvio lo que hace... > Por último, la expresión @hosts[0].cliente.nombre o > @hosts.first.cliente.nombre me da lo que busco, pero realiza consultas > adicionales a la base que en este caso pequeño no sería problema, pero sí > con tablas que manejan varios millones de registros tal como ocurre con > otras de mis tablas. > primero encontrate con este problema, medí, y luego cambiá esto @hosts = Host.all por @hosts = Host.all :include => :cliente nada más (la consulta es igual) Primero resolvé el problema, después optimizá. ¡¡Saludos y suerte!! nachokb
_______________________________________________ Ruby mailing list [email protected] http://lista.rubyargentina.com.ar/listinfo.cgi/ruby-rubyargentina.com.ar
