2010-10-15 13 views
5

Estoy tratando desesperadamente de darle sentido a Arel, sobre todo porque odio lidiar con SQL; Lo estaba haciendo muy bien, pero choqué contra una pared.¿Qué acaba de pasar con Arel y qué hago con un Arel :: SelectManager?

He estado trabajando en Rails 3.0.0, y estoy tratando de hacer una consulta compleja con algunos cálculos matemáticos. El caso real es bastante más complejo, pero me he simplificado un poco. En mi ejemplo, tengo una tabla con un campo de cadena particular, y quiero un recuento de todos los registros, así como un recuento para cada uno de los dos posibles valores de ese campo, agrupados por una identificación extranjera.

rieles Bajo 3.0.0, no puedo hacer esto (los comandos de consola):

t = Arel::Table.new(:some_thingies) 
e = t         .project(t[:foreign_id], t[:foreign_id].count.as('all_count')) .group(t[:foreign_id]) 
c = t.where(t[:some_field].eq('type1')).project(t[:foreign_id], t[:foreign_id].count.as('type1_count')).group(t[:foreign_id]) 
x = e 
x = x.join(c).on(e[:foreign_id].eq(c[:foreign_id])) 

y en este punto que puedo hacer hacer x.to_sql y ... bueno, no estoy del todo seguro de que es correcto, pero los resultados se ven bien, aparte de tener la columna foreign_id dos veces.

SELECT  
    `some_thingies_external`.`foreign_id`, 
    `some_thingies_external`.`all_count`, 
    `some_thingies_external_2`.`foreign_id`, 
    `some_thingies_external_2`.`type1_count` 
FROM  
    (SELECT  
    `some_thingies`.`foreign_id`, COUNT(`some_thingies`.`foreign_id`) 
    AS `type1+count` 
    FROM  `some_thingies` 
    GROUP BY `some_thingies`.`foreign_id`) `some_thingies_external` 
INNER JOIN 
    (SELECT  `some_thingies`.`foreign_id`, COUNT(`some_thingies`.`foreign_id`) 
    AS `type1_count` 
    FROM  `some_thingies` 
    WHERE  `some_thingies`.`type` = 'type1' 
    GROUP BY `some_thingies`.`foreign_id`) `some_thingies_external_2` 
ON `some_thingies_external`.`foreign_id` = `some_thingies_external_2`.`foreign_id` 

Hasta ahora todo bien. Sin embargo, cuando trato de unirse a un segundo conjunto de recuentos de esta manera:

i = t.where(t[:some_field].eq('type2')).project(t[:foreign_id], t[:foreign_id].count.as('type2_count')).group(t[:foreign_id]) 
x = x.join(i).on(e[:foreign_id].eq(i[:foreign_id])) 

simplemente se cuelga, lo que lleva a pensar que me estoy golpeando this bug

(más cargos por cierto que tengo que agregar, e idealmente 'some_thingies' debería ser un objeto arel que representa más filtrado en qué thingies estamos contando ... pero estoy divagando ...)

Así que decidí probar el último borde de Arel y Rieles, y aumentó mis gemas en consecuencia:

gem 'rails', :git => 'git://github.com/rails/rails.git' 
gem 'rack', :git => 'git://github.com/rack/rack.git' 
gem 'arel', :git => 'http://github.com/brynary/arel.git' 

y ahora cuando trato de hacer hacer la primera unen, falla estrepitosamente:

ruby-1.9.2-preview3 >  x = x.join(c).on(e[:foreign_id].eq(c[:foreign_id])) 
NoMethodError: undefined method `[]' for #<Arel::SelectManager:0x00000104311e38> 
    from (irb):12 
    from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands/console.rb:44:in `start' 
    from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands/console.rb:8:in `start' 
    from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands.rb:33:in `<top (required)>' 
    from script/rails:6:in `require' 
    from script/rails:6:in `<main>' 

Esto no parece ser un error en Arel - en todo caso, parece más como el hecho de que trabajado antes es el error. Creo que simplemente no sé qué es Arel :: SelectManager y qué hacer con él. Parecía que lo estaba haciendo muy bien, pero realmente no entiendo lo que está pasando.

¿Debo de alguna manera hacer una nueva tabla basada en el SelectManager que tengo? ¿O estoy haciendo algo mal en mi configuración que hace que la sintaxis [] falle? ¿O simplemente no logro entender qué hace Arel? Aún no entiendo lo que se supone que debo hacer con Arel :: Rows, pero supongo que me haré una idea de eso; y sospecho que puedo deshacerme de la clave externa extra en los resultados con un proyecto() ...

Pero todavía estoy bastante perdido. Haaaaalp!

p.s. ¿'riman' las 'rabies' con 'fragilidad' o con 'mail guys'?

Respuesta

3

Voy a responder mi propia pregunta, ya que nadie parece interesado, y ahora que sé lo que estoy haciendo mal, puedo ver que sería obvio si entendiera SQL.

Problema 1 con la forma en que estaba usando Arel es que solo puedes unirte a una mesa recién hecha. Eso está fuera del punto.

El verdadero problema es que estoy tratando de contar dos cosas diferentes. Realmente debería estar agrupando por la ID extranjera Y el 'some_field'. Simplemente no sabía que podrías hacer eso, y los resultados son un poco raros.Si no me importan todos los valores posibles de some_field, esto puede ser molesto, pero me importan todos, y puedo sumarlos con la suficiente facilidad para obtener el total, y es fácil filtrarlos ahora.

t = Arel::Table.new(:some_thingies)  
e = t.group(:foreign_id, :some_field).project(t[:id], t[:foreign_id], t[:some_field]) 

Una vez que me di cuenta de eso, me di cuenta de cómo hacerlo con ActiveRecord normal y sin Arel:

SomeThing.group('foreign_id, some_field').select('id, foreign_id, some_field, count(1)') 

D'oh! Moral: SQL solo conoce las filas. Período.

+1

Yo también estoy recibiendo un SelectManager y no sé Qué hacer con ello. Esta respuesta tuya no responde esta pregunta. De todos modos, si considera que la respuesta que se está dando es la respuesta correcta, quizás debería marcar como "respuesta correcta". –

+0

sí, realmente no tengo una respuesta adecuada. Creo que lo que realmente estaba preguntando es "¿podría alguien mostrarme cómo usar Arel de una manera práctica?". He renunciado a eso y estoy obteniendo muy buenos resultados con Squeel https://github.com/ernie/squeel –

+0

Hm ... Solo mi opinión: supongo que no está intentando demasiado. Nunca he usado la cláusula grupal en arel, sin embargo, he estado usándola cada vez más con deleite. –

3

Arel ha sido completamente renovado desde las entrañas. Esta iniciativa fue iniciada por tenderlove (Aaron) Hubo problemas de problemas de rendimiento en consultas en gran parte compuestas.

Incluso he hecho contribuciones a esta nueva iniciativa.

Arel ahora usa el Árbol de sintaxis abstracta (dentro del Administrador de selección) y el Patrón de visitante.

Es lo mismo que el desguace de la manera en que Arel 1.0.1 trabajos en el sabor de 2.0.0 (a la manera de 3.0.x para alinearse con rieles)

Cuestiones relacionadas