如何通过关系显示has_many的唯一logging?

我想知道什么是通过Rails3中的关系来显示来自has_many的唯一logging的最佳方式。

我有三个模型:

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 

比方说,我想列出客户已经在他们的显示页面上订购的所有产品。

他们可能已经多次订购一些产品,所以我使用counter_cache根据订单数量以降序排列显示。

但是,如果他们多次订购产品,我需要确保每个产品只列出一次。

 @products = @user.products.ranked(:limit => 10).uniq! 

当一个产品有多个订单logging时工作,但如果一个产品只被订购了一次,则产生一个错误。 (排名是在别处定义的自定义sorting函数)

另一种select是:

 @products = @user.products.ranked(:limit => 10, :select => "DISTINCT(ID)") 

我不确定我在这里是正确的做法。

有没有其他人解决这个问题? 你遇到了什么问题? 我在哪里可以find更多关于.unique的区别! 和DISTINCT()?

通过has_many关系生成唯一logging列表的最好方法是什么?

谢谢

你是否试图在has_many关联中指定:uniq选项:

 has_many :products, :through => :orders, :uniq => true 

从Rails文档 :

:uniq

如果为true,则将从集合中省略重复项。 与…一起使用。

更新轨道4:

在Rails 4中, has_many :products, :through => :orders, :uniq => true已被弃用。 相反,您现在应该has_many :products, -> { distinct }, through: :orders编写has_many :products, -> { distinct }, through: :orders 。 有关更多信息,请参阅has_many ::截然不同的部分:通过ActiveRecord关联文档中的关系 。 感谢Kurt Mueller在他的评论中指出了这一点。

请注意,从Rails 4的has_many的有效选项中删除了uniq: true

在Rails 4中,你必须提供一个范围来configuration这种行为。 范围可以通过lambdas提供,如下所示:

 has_many :products, -> { uniq }, :through => :orders 

导轨指南涵盖了这个以及其他方式,您可以使用示波器来过滤关系的查询,向下滚动到4.3.3节:

http://guides.rubyonrails.org/association_basics.html#has-many-association-reference

你可以使用group_by 。 例如,我有一个照片库购物车,我希望通过哪个照片(每张照片可以多次订购,以不同尺寸打印)对订购商品进行分类。 这然后返回一个散列与产品(照片)作为关键,每次它的sorting可以在照片(或不)的上下文中列出。 使用这种技术,您可以实际输出每个给定产品的订单历史logging。 不知道在这种情况下这对你是否有帮助,但我发现它非常有用。 这是代码

 OrdersController#show @order = Order.find(params[:id]) @order_items_by_photo = @order.order_items.group_by(&:photo) 

@order_items_by_photo然后看起来像这样:

 => {#<Photo id: 128>=>[#<OrderItem id: 2, photo_id: 128>, #<OrderItem id: 19, photo_id: 128>] 

所以你可以做这样的事情:

 @orders_by_product = @user.orders.group_by(&:product) 

然后当你在你的视图中得到这个,只是循环这样的事情:

 - for product, orders in @user.orders_by_product - "#{product.name}: #{orders.size}" - for order in orders - output_order_details 

这样可以避免仅返回一个产品时出现的问题,因为您始终知道它将以产品作为关键字和您的订单数组返回散列。

对于你想要做的事情可能是过度的,但它确实给你一些不错的select(如订购的date等)来处理数量。