And*_*vey 101 ruby-on-rails unique distinct ruby-on-rails-3
我想知道在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
Run Code Online (Sandbox Code Playgroud)
假设我想列出客户在其展示页面上订购的所有产品.
他们可能多次订购了一些产品,所以我使用counter_cache以降序排序,根据订单数量显示.
但是,如果他们多次订购产品,我需要确保每个产品只列出一次.
@products = @user.products.ranked(:limit => 10).uniq!
Run Code Online (Sandbox Code Playgroud)
当产品有多个订单记录时有效,但如果产品只订购一次,则会产生错误.(排名是在别处定义的自定义排序函数)
另一种选择是:
@products = @user.products.ranked(:limit => 10, :select => "DISTINCT(ID)")
Run Code Online (Sandbox Code Playgroud)
我不相信我在这里采取了正确的方法.
有没有其他人解决这个问题?你遇到了什么问题?我在哪里可以找到更多关于.unique之间的区别!和DISTINCT()?
通过has_many,通过关系生成唯一记录列表的最佳方法是什么?
谢谢
mbr*_*ing 225
您是否尝试在has_many关联上指定:uniq选项:
has_many :products, :through => :orders, :uniq => true
Run Code Online (Sandbox Code Playgroud)
从Rails文档:
:uniq如果为true,则将从集合中省略重复项.与以下内容结合使用:通过.
铁路4的最新消息:
在Rails 4中,has_many :products, :through => :orders, :uniq => true已弃用.相反,你现在应该写has_many :products, -> { distinct }, through: :orders.有关详细信息,请参阅has_many的distinct部分::通过ActiveRecord Associations文档中的关系.感谢Kurt Mueller在评论中指出这一点.
Yos*_*iki 41
请注意,uniq: true已从has_manyRails 4 的有效选项中删除.
在Rails 4中,您必须提供范围来配置此类行为.范围可以通过lambdas提供,如下所示:
has_many :products, -> { uniq }, :through => :orders
Run Code Online (Sandbox Code Playgroud)
rails指南涵盖了这个以及您可以使用范围来过滤关系查询的其他方式,向下滚动到第4.3.3节:
http://guides.rubyonrails.org/association_basics.html#has-many-association-reference
小智 12
在rails6中使用-> { distinct }范围内它将起作用
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>]
Run Code Online (Sandbox Code Playgroud)
你可以用group_by.例如,我有一个照片库购物车,我希望订购商品按照哪张照片进行分类(每张照片可以多次订购,尺寸不同.)然后,这将返回带有产品(照片)作为关键字的哈希值,并且每次订购时都可以在照片的上下文中列出(或不列出).使用此技术,您实际上可以输出每个给定产品的订单历史记录.在这种情况下,不确定这对你是否有帮助,但我发现它非常有用.这是代码
OrdersController#show
@order = Order.find(params[:id])
@order_items_by_photo = @order.order_items.group_by(&:photo)
Run Code Online (Sandbox Code Playgroud)
@order_items_by_photo 然后看起来像这样:
=> {#<Photo id: 128>=>[#<OrderItem id: 2, photo_id: 128>, #<OrderItem id: 19, photo_id: 128>]
Run Code Online (Sandbox Code Playgroud)
所以你可以这样做:
@orders_by_product = @user.orders.group_by(&:product)
Run Code Online (Sandbox Code Playgroud)
然后当你在视图中得到它时,只需循环这样的事情:
- for product, orders in @user.orders_by_product
- "#{product.name}: #{orders.size}"
- for order in orders
- output_order_details
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以避免在仅返回一个产品时出现的问题,因为您始终知道它将返回带有产品作为键和订单数组的哈希.
对于您正在尝试做的事情可能有点过头了,但除了数量之外,它确实为您提供了一些不错的选项(即订购日期等).
小智 5
在 Rails 6 上,我让它完美地工作:
has_many :regions, -> { order(:name).distinct }, through: :sites
Run Code Online (Sandbox Code Playgroud)
我无法得到任何其他的工作答案。