Rails 选择 GROUP 中 COUNT 最高的对象 [英] Rails select the object with the highest COUNT in a GROUP

查看:63
本文介绍了Rails 选择 GROUP 中 COUNT 最高的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标是选择Coupon最常使用的Store.

The goal is to select the Store in which a Coupon is most used at.

目前,我有这个,它可以工作(为了解释而分解):

Currently, I have this, and it works (broken down for explanation):

# coupon.rb
  has_many :redemptions
  has_and_belongs_to_many :stores

  def most_popular_store
    stores.find(        # Return a store object
      redemptions       # Start with all of the coupon's redemptions
      .group(:store_id) # Group them by the store_id
      .count            # Get a hash of { 'store_id' => 'count' } values
      .keys             # Create an array of keys
      .sort             # Sort the keys so highest is first
      .first            # Take the ID of the first key
    )
  end
###

它是这样使用的:

describe 'most_popular_store' do
    it 'returns the most popular store' do
        # Create coupon
        coupon = FactoryGirl.create(:coupon)

        # Create two different stores
        most_popular_store = FactoryGirl.create(:store, coupons: [coupon])
        other_store        = FactoryGirl.create(:store, coupons: [coupon])

        # Add redemptions between those stores
        FactoryGirl.create_list(:redemption, 2, coupon: coupon, store: other_store)
        FactoryGirl.create_list(:redemption, 5, coupon: coupon, store: most_popular_store)

        # Verify
        expect(coupon.most_popular_store.title).to eq most_popular_store.title
    end
end

就像我说的,该方法有效,但它看起来像猴子补丁.如何重构我的 most_popular_store 方法?

Like I said, the method works, but it looks monkeypatched. How can I refactor my most_popular_store method?

推荐答案

我认为您的方法实际上不起作用.count 为您提供一个以键作为 store_ids 和值作为计数的散列,然后您在散列上运行 keys,它为您提供一个 store_id 数组.从那时起,您已经失去了计数,您正在按 store_ids 排序并获取第一个.您的测试通过的唯一原因是您在另一个之前创建了流行商店,因此它的 id 较低(sort 默认情况下按升序排序).要获得正确的结果,请进行以下更改:

I think your method actually doesn't work. count gives you a hash with keys as store_ids and values as counts, then you run keys on the hash, which gives you an array of store_ids. From then on, you have lost the counts, you are sorting by store_ids and grabbing the first one. The only reason your test passes is that you are creating the popular store before the other one, hence it gets a lower id (sort does the sort ascending by default). To get a correct result, make the following change:

redemptions       # Start with all of the coupon's redemptions
  .group(:store_id) # Group them by the store_id
  .count            # Get a hash of { 'store_id' => 'count' } values
  .max_by{|k,v| v}  # Get key, val pair with the highest value
                    # output => [key, value]
  .first            # Get the first item in array (the key)

这篇关于Rails 选择 GROUP 中 COUNT 最高的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆