bien, gracias a tadman para mí empujando en la dirección correcta.
He cavado algo más profundo (especialmente en los archivos de registro) y lo que encontré es un poco extraño.
El problema fue causado por el número de columnas seleccionadas. Si uno selecciona sólo una columna y cuenta el resultado
my_meal.noodles.select("distinct color").count
ActiveRecord crea la siguiente instrucción SQL:
SELECT COUNT(distinct color) AS count_id FROM "NOODLES" WHERE ("NOODLES".meal_id = 295)
En caso de que uno selecciona dos o más columnas y se aplica count
a ella
my_meal.noodles.select("distinct color, shape").count
ActiveRecord se olvida de esa cláusula de selección y crea:
SELECT COUNT(*) AS count_id FROM "NOODLES" WHERE ("NOODLES".meal_id = 295)
Esto puede ser correcto, ya que (SQL) COUNT
permite solo una o menos columnas como parámetros. Añadir un group
antes de la count
y todo está bien:
my_meal.noodles.select("distinct color, shape").group("color, shape").count
SELECT COUNT(*) AS count_all, color, shape AS color_shape FROM "NOODLES" WHERE ("NOODLES".meal_id = 295) GROUP BY color, shape
Aparte de esto AS color_shape
es exactamente lo que esperaba. PERO...solamente devuelve esto:
>> my_meal.noodles.select("distinct color, shape").group("color, shape").count
=> {star=>309, circle=>111, spaghetti=>189, square=>194, triangle=>179, bowtie=>301, shell=>93, letter=>230}
>> my_meal.noodles.select("distinct color, shape").group("color, shape").count.class
=> ActiveSupport::OrderedHash
Este valor de retorno extraño es (aparte de orden que depende de la DB) idéntico con el valor del resultado y el retorno de
my_meal.noodles.group("shape").count
Conclusión:
Como pointed out here hay todavía hay una brecha entre las relaciones (pueden ser relaciones matemáticas o areales) y ActiveRecord :: Relations.
Veo las ventajas de presionar el resultado en los patrones de un modelo tan a menudo como sea posible (al menos en el contexto de una aplicación de Rails).
Sin embargo, las relaciones reales no son el resultado de la combinación de varias operaciones, sino el resultado de la concatenación de esas operaciones. En general, la capacidad de ocultación de ActiveRecord :: Relations es una gran cosa, pero hay algunas decisiones de diseño que no puedo seguir.
Si no puede confiar en la seguridad de que cada acción devuelve una nueva relación para trabajar, pierde gran parte de su atractivo inicial.
En cuanto a la solución de mi problema, voy a utilizar la solución mencionada group
y algún tipo de solución sucia para la operación de conteo:
my_meal.noodles.select("distinct color, shape").group("color, shape").all.count
Esto comprime los resultados a un mínimo aceptable antes de tirar de ellas fuera de la base de datos y crear objetos caros solo para contarlos. Alternativamente, uno podría usar una consulta SQL manuscrita, pero ¿por qué tener un Rails y no usarlo, eh? ;-)
Gracias por su ayuda,
Tim
Se puede investigar lo que se está generando SQL y publicar aquí? Esto se almacenará en 'log/development.log' y generalmente es muy revelador. – tadman
Para mirar más profundo intente 'to_sql':' my_meal.noodles.select ("distinct color, shape"). Count.to_sql'. – fl00r
En realidad, acabo de intentar con la misma prueba y en mi caso todo funciona bien. Count ha hecho su trabajo perfecto – fl00r