2016-12-09 2 views
0

Ich würde gerne den Code unten in mehr wie Ruby Weise zu umgestalten.Schienen; Summe

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

Grundsätzlich iterieren Sie einfach Objekt, holen Sie die einzelnen Beträge und geben Sie die Summe zurück. Irgendeine Idee?

Update

total = item.itemable.amount ist richtig.

+0

Was itemable ist, kann es mit einer einzigen Abfrage als auch – RSB

+0

Produkte haben polymorphe Beziehungen zu anderen Modellen durchgeführt werden. – Tosh

+0

@TSH Fügen Sie Ihre Assoziationen hinzu. 'items.itemable' - funktioniert das? – dp7

Antwort

1

können Sie versuchen, die folgenden:

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

Die genaue Syntax auf Ihren Code abhängt. Obwohl es nicht unbedingt ein Ruby Way ist, ist es prägnanter und funktionaler Stil.

+3

kann auch geschrieben werden als 'items.map (&: amount) .reduce (& +)' oder in Rails 'items.map (&: amount) .sum' – user000001

+0

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

+0

@ user000001, das ist wahr,' inject' und 'reduce' sind fast die gleichen in ruby. – Sid

0

Versuchen Sie dies für Ihren Verein:

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

ODER

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

Das ist nicht 'NoMethodError funktioniert: undefined Methode + '' – Tosh

+0

@TSH aktualisiert Antwort – dp7

+0

Ihre Antwort bearbeiten repliziert meine Antwort! :) – RSB

1

Sie dies tun können, ich bin gespannt Belastung durch includes mit n + 1 Abfrage Problem

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

Hoffnung zu vermeiden das hilft!

0

Sie können von sum

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

machen Es gibt eine weitere Sache, die Sie tun können, während Refactoring.

In Artikel Modell können Sie Menge Methode delegieren itemable

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

Jetzt können Sie Menge ohne . Operator erhalten.

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

Mit prefix: false Sie schreiben können,

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

Sie können die Gesamtsumme auf diese Weise, ich denke, das ist die beste Praxis ist und die effizienteste in Sachen Leistung

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