Me pregunto cuál es la mejor manera de mostrar registros únicos de has_many, a través de la relación en 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 presentación.
Es posible que hayan pedido algunos productos varias veces, por lo que estoy usando counter_cache para mostrarlos en orden de clasificación descendente, según la cantidad de pedidos.
Pero, si han pedido un producto varias veces, debo asegurarme de que cada producto solo aparezca una vez.
@products = @user.products.ranked(:limit => 10).uniq!
funciona cuando hay varios registros de pedidos para un producto, pero genera un error si un producto solo se ha pedido una vez. (clasificado es la 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 estar en el enfoque correcto aquí.
¿Alguien más ha abordado esto? ¿A qué problemas te enfrentaste? ¿Dónde puedo encontrar 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?
Gracias
fuente
has_many :products, :through => :orders, :uniq => true
está en desuso. En su lugar, ahora debería escribirhas_many :products, -> { uniq }, through: :orders
.DISTINCT
yORDER BY
, siempre puede usarhas_many :products, -> { unscope(:order).distinct }, through: :orders
has_many :subscribed_locations, -> { unscope(:order).select("DISTINCT ON (locations.id) locations.*") },through: :people_publication_subscription_locations, class_name: 'Location', source: :location
contrario, obtienerails ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR: could not identify an equality operator for type json
Tenga en cuenta que
uniq: true
se ha eliminado de las opciones válidas parahas_many
Rails 4.En Rails 4 tienes que proporcionar un alcance para configurar este tipo de comportamiento. Los alcances se pueden suministrar a través de lambdas, así:
La guía de rieles cubre esta y otras formas en las que puede usar ámbitos para filtrar las consultas de su relación, desplácese hacia abajo hasta la sección 4.3.3:
http://guides.rubyonrails.org/association_basics.html#has-many-association-reference
fuente
undefined method 'except' for #<Array...
y fue porque usé en.uniq
lugar de.distinct
Podrías usar
group_by
. Por ejemplo, tengo un carrito de compras de la galería de fotos para el cual quiero ordenar los artículos por qué foto (cada foto se puede pedir varias veces y en impresiones de diferentes tamaños). Esto luego devuelve un hash con el producto (foto) como 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 dado. No estoy seguro de si eso es útil para usted en este contexto, pero lo encontré bastante útil. Aqui esta el codigo@order_items_by_photo
luego se ve algo como esto:Entonces podrías hacer algo como:
Luego, cuando tenga esto en su vista, simplemente recorra algo como esto:
De esta manera evita el problema que se ve al devolver un solo producto, ya que siempre sabe que devolverá un hash con un producto como clave y una matriz de sus pedidos.
Puede ser exagerado para lo que está tratando de hacer, pero le brinda algunas opciones agradables (es decir, fechas ordenadas, etc.) con las que trabajar además de la cantidad.
fuente
En Rails 6 conseguí que esto funcionara perfectamente:
No pude hacer que ninguna de las otras respuestas funcionara.
fuente