有没有更惯用的方法来实现我的'check_count'方法?

时间:2018-06-14 01:18:46

标签: ruby-on-rails

我的问题是,为check_count课程实施Deposit方法是否有更简单或更惯用的方法?

这是(长)背景。在我当前的项目中,我有类LineItem

# == Schema Information
#
# Table name: line_items
#
#  id                 :integer          not null, primary key
#  customer_id        :integer          not null
#  item_type_id       :integer          not null
#  amount_cents       :integer          not null
#  amount_currency    :string           not null
#  check_number       :string
#  lineable_type      :string 
#  lineable_id        :integer
#  created_at         :datetime         not null
#  updated_at         :datetime         not null
#
class LineItem < ActiveRecord::Base

  belongs_to :lineable, polymorphic: true

  validates :lineable_type,
            :lineable_id,
            :customer_id,
            :item_type,
            :amount_cents,
            :amount_currency,
            presence: true

  validates :check_number, presence: true, if: :check?

  enum item_type: {
    check:  0,
    cash:   1
  }

  def check?; item_type == :check end

end

Deposit

class Deposit < ActiveRecord::Base

  has_many  :line_items,
            as: :lineable,
            dependent: :destroy

  def check_items
    line_items.where(item_type: LineItem.item_types['check'])
  end

  def check_count
    check_items.
      group_by(&:customer_id).
      transform_values{|v| v.map(&:check_number).uniq.count}.
      values.
      sum
  end

end

所以,如果在我的line_items表中,我有(省略不相关的位):

--------------------------------------------------------------------------------
| id | customer_id | item_type_id | check_number | lineable_type | lineable_id |
--------------------------------------------------------------------------------
| 1  | 1           | 0            | 9989         | 'Deposit'     | 1           |
| 2  | 1           | 0            | 9989         | 'Deposit'     | 1           |
| 3  | 2           | 0            | 9989         | 'Deposit'     | 1           |
--------------------------------------------------------------------------------

我能做到:

Deposit.find(1).check_count
 => 2

哪个是正确的结果。

check_count方法对我来说似乎很笨拙。我错过了一些更干净的方法吗?

我正在使用rails 4.2.8和ruby 2.5.1。

1 个答案:

答案 0 :(得分:1)

据我了解,您正在为每位客户汇总所有唯一的支票号码。

您可以使用SQL的GROUP BY功能来完成此操作。这是关于如何进行双列分组的good example。 因此,要在ActiveRecord(AR)中获得相同的结果,您可以执行类似的操作。

  def check_count
    check_items.group(:customer_id, :check_number).count.count
  end

注意:因为您对许多此类群组感兴趣,我们会拨打#count 2次。 在第一次调用时,将使用

调用AR关系
check_items.group(:customer_id, :check_number).count #=> {[1, '9989'] => 2, [2, '9989'] => 1}

第二次调用count将计算组的数量

{[1, '9989'] => 2, [2, '9989'] => 1}.count # => 2