我的问题是,为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。
答案 0 :(得分:1)
据我了解,您正在为每位客户汇总所有唯一的支票号码。
您可以使用SQL的GROUP BY
功能来完成此操作。这是关于如何进行双列分组的good example。
因此,要在ActiveRecord(AR)中获得相同的结果,您可以执行类似的操作。
def check_count
check_items.group(:customer_id, :check_number).count.count
end
注意:因为您对许多此类群组感兴趣,我们会拨打#count
2次。
在第一次调用时,将使用
check_items.group(:customer_id, :check_number).count #=> {[1, '9989'] => 2, [2, '9989'] => 1}
第二次调用count将计算组的数量
{[1, '9989'] => 2, [2, '9989'] => 1}.count # => 2