[英]How to display non-unique records from a has_many through relationship in ActiveRecord?
[英]How to display unique records from a has_many through relationship?
我想知道通过 Rails3 中的关系显示 has_many 中唯一记录的最佳方式是什么。
我有三个模型:
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!
当一个产品有多个订单记录时有效,但如果一个产品仅被订购一次,则会生成错误。 (排名是在别处定义的自定义排序 function)
另一种选择是:
@products = @user.products.ranked(:limit => 10, :select => "DISTINCT(ID)")
我不确定我在这里的方法是否正确。
有没有其他人解决过这个问题? 你遇到了什么问题? 我在哪里可以找到更多关于.unique 的区别的信息? 和不同()?
通过has_many,通过关系生成唯一记录列表的最佳方法是什么?
谢谢
您是否尝试在 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
。 有关更多信息,请参阅ActiveRecord 关联文档上的 has_many: :through 关系的不同部分。 感谢 Kurt Mueller 在评论中指出这一点。
请注意,从 Rails 4 开始,已经从has_many
的有效选项中删除了uniq: true
。
在 Rails 4 中,您必须提供 scope 来配置这种行为。 范围可以通过 lambdas 提供,如下所示:
has_many :products, -> { uniq }, :through => :orders
rails 指南涵盖了这个和其他可以使用范围过滤关系查询的方法,向下滚动到第 4.3.3 节:
http://guides.rubyonrails.org/association_basics.html#has-many-association-reference
您可以使用group_by
。 例如,我有一个相册购物车,我希望按哪张照片对订购的商品进行排序(每张照片可以多次订购,并且打印尺寸不同)。 然后返回一个 hash ,其中产品(照片)作为键,每次订购时都可以在照片的上下文中列出(或不列出)。 使用这种技术,您实际上可以为每个给定产品 output 一个订单历史记录。 不确定在这种情况下这是否对您有帮助,但我发现它非常有用。 这是代码
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
这样您就可以避免只返回一个产品时出现的问题,因为您始终知道它将返回 hash,其中一个产品作为键和您的订单数组。
对于您尝试做的事情来说,这可能有点矫枉过正,但除了数量之外,它确实为您提供了一些不错的选择(即订购的日期等)。
在 Rails 6 上,我让它完美地工作:
has_many :regions, -> { order(:name).distinct }, through: :sites
我无法得到任何其他答案。
在 rails6 使用-> { distinct }
在 scope 它将工作
class Person
has_many :readings
has_many :articles, -> { distinct }, through: :readings
end
person = Person.create(name: 'Honda')
article = Article.create(name: 'a1')
person.articles << article
person.articles << article
person.articles.inspect # => [#<Article id: 7, name: "a1">]
Reading.all.inspect # => [#<Reading id: 16, person_id: 7, article_id: 7>, #<Reading id: 17, person_id: 7, article_id: 7>]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.