ruby-on-rails - includes - rails query uniq
¿Cómo mostrar registros únicos de una relación has_many through? (3)
¿Has intentado especificar la opción: uniq en la asociación has_many:
has_many :products, :through => :orders, :uniq => true
De la documentación de Rails :
:uniq
Si es verdadero, los duplicados se omitirán de la colección. Útil en conjunción con: a través de.
ACTUALIZAR PARA RAILS 4:
En Rails 4, has_many :products, :through => :orders, :uniq => true
está en desuso. En su lugar, ahora debe escribir has_many :products, -> { distinct }, through: :orders
. Consulte la sección distinta de has_many:: a través de las relaciones en la documentación de Asociaciones ActiveRecord para obtener más información. Gracias a Kurt Mueller por señalar esto en su comentario.
Me pregunto cuál es la mejor manera de mostrar registros únicos de una relación has_many, a través de Rails3.
Tengo tres modelos:
class User < ActiveRecord::Base
has_many :orders
has_many :products, :through => :orders
end
class Products < ActiveRecord::Base
has_many :orders
has_many :users, :through => :orders
end
class Order < ActiveRecord::Base
belongs_to :user, :counter_cache => true
belongs_to :product, :counter_cache => true
end
Digamos que quiero enumerar todos los productos que un cliente ha pedido en su página de muestra.
Es posible que hayan ordenado algunos productos varias veces, por lo que estoy usando counter_cache para mostrarlos en orden descendente según el número de pedidos.
Pero, si han ordenado un producto varias veces, debo asegurarme de que cada producto aparezca solo una vez.
@products = @user.products.ranked(:limit => 10).uniq!
funciona cuando hay múltiples registros de pedidos para un producto, pero genera un error si un producto solo se ha pedido una vez. (clasificado es una función de clasificación personalizada definida en otro lugar)
Otra alternativa es:
@products = @user.products.ranked(:limit => 10, :select => "DISTINCT(ID)")
No estoy seguro de que estoy en el enfoque correcto aquí.
¿Alguien más ha abordado esto? ¿Qué problemas te enfrentaste? ¿Dónde puedo obtener más información sobre la diferencia entre .unique! y DISTINCT ()?
¿Cuál es la mejor manera de generar una lista de registros únicos a través de una relación has_many, through?
Gracias
Puede usar group_by
. Por ejemplo, tengo un carrito de compras de la galería de fotos para el que quiero ordenar los elementos para clasificar por cada foto (cada foto se puede pedir varias veces y en diferentes tamaños de copias). Esto luego devuelve un hash con el producto (foto) como la clave y cada vez que se ordenó se puede enumerar en el contexto de la foto (o no). Con esta técnica, podría generar un historial de pedidos para cada producto. No estoy seguro si eso es útil para usted en este contexto, pero lo encontré bastante útil. Aquí está el código
OrdersController#show
@order = Order.find(params[:id])
@order_items_by_photo = @order.order_items.group_by(&:photo)
@order_items_by_photo
se ve así:
=> {#<Photo id: 128>=>[#<OrderItem id: 2, photo_id: 128>, #<OrderItem id: 19, photo_id: 128>]
Entonces podrías hacer algo como:
@orders_by_product = @user.orders.group_by(&:product)
Luego, cuando tengas esto en tu punto de vista, simplemente recorre algo como esto:
- for product, orders in @user.orders_by_product
- "#{product.name}: #{orders.size}"
- for order in orders
- output_order_details
De esta forma evitará el problema que se observa al devolver solo un producto, ya que siempre sabe que devolverá un hash con un producto como la clave y una matriz de sus pedidos.
Puede ser excesivo para lo que está tratando de hacer, pero le da algunas opciones agradables (es decir, fechas pedidas, etc.) para trabajar además de la cantidad.
Tenga en cuenta que uniq: true
ha sido eliminado de las opciones válidas para has_many
partir de Rails 4.
En Rails 4 debe proporcionar un alcance para configurar este tipo de comportamiento. Los alcances se pueden suministrar a través de lambdas, así:
has_many :products, -> { uniq }, :through => :orders
La guía de rieles cubre esta y otras formas en que puede usar ámbitos para filtrar las consultas de su relación, baje hasta la sección 4.3.3:
http://guides.rubyonrails.org/association_basics.html#has-many-association-reference