2016-12-09 79 views
0

我很想用Ruby的方式重構下面的代碼。導軌;總計

def cal_total 
    total = nil 
    items.each do |item| 
     total = total + item.itemable.amount 
    end 
    total 
end 

基本上只是迭代對象,獲取每個數量,並返回總數。 有什麼想法?

更新

total = item.itemable.amount是正確的。

+0

什麼是可迭代的,它可以通過單個查詢來完成 – RSB

+0

項目與其他模型具有多態關係。 – Tosh

+0

@TSH添加您的關聯。 'items.itemable' - 做這個工作嗎? – dp7

回答

1

你可以嘗試以下方法:

items.map(&:amount).inject(0, &:+) 

確切語法取決於你的代碼。雖然不一定是Ruby Way,但它更簡潔和實用。

+3

也可以寫成'items.map(&:amount).reduce(&:+)'或Rails'items.map(&:amount).sum' – user000001

+0

'items.itemable.map (&:amount).inject(0,&:+)' – Kris

+0

@ user000001,這是真的,'inject'和'reduce'在ruby中幾乎是一樣的。 – Sid

0

試試這個你聯想:

items.map(&:itemable).sum(&:amount) 

OR

items.map { |i| i.itemable.amount }.sum 
+0

This does not work'NoMethodError:undefined method +' – Tosh

+0

@TSH更新回答 – dp7

+0

您的回答編輯複製我的答案! :) – RSB

1

你可以做到這一點,我渴望加載使用includes避免n + 1查詢問題

items = Item.includes(:itemable) 
total = items.map{ |item| item.itemable.amount }.sum 

希望這有幫助!

0

您可以使用sum

items.map{ |item| item.itemable.amount }.sum 
1

有一個重構的同時,你可以做更多的事情。

在項目模型,你可以委託量的方法來itemable

class Item 
    delegate :amount, to: :itemable, prefix: true, allow_nil: true 
end 

現在你可以不用量操作.

items.map{ |item| item.itemable_amount }.sum 

隨着prefix: false你可以寫,

items.map{ |item| item.amount }.sum 
0

你可以得到全額這種方式,我覺得這是最好的實踐和最高效的性能無論

items.map(:&itemable).pluck(:amount).reduce(:+)