2014-06-30 16 views
16

Io uso payments.sum(&:price) nella mia app Rails (4.1.2). da quando ho aggiornato da Ruby 1.9.3 a 2.1.2, ottengo questi errori:sum (&: x) non funziona più

wrong number of arguments (1 for 2..3) 

queste varianti lavoro:

payments.map(&:price).sum 
payments.to_a.sum(&:price) 

Devo riscrivere il mio codice o mi sono perso qualcosa? Grazie!

+2

Che cosa significa "pagamenti"? Rails ha due diversi metodi 'sum': [Enumerable # sum] (http://apidock.com/rails/Enumerable/sum) e [ActiveRecord :: Relation # sum] (http://api.rubyonrails.org/classes /ActiveRecord/Calculations.html#method-i-sum). Il primo prende un blocco (che è il motivo per cui '&', l'operatore 'to_proc', funziona); il secondo no. Indipendentemente da ciò, sono abbastanza sicuro che l'aggiornamento di Ruby da 1.9.3 a 2.1 sia un'aringa rossa. Il comportamento di '&' non è cambiato tra quelle versioni. –

risposta

17

Dal documentation:

somma (* args)

calcola la somma dei valori su una data colonna. Il valore viene restituito con lo stesso tipo di dati della colonna, 0 se non ci sono righe. Vedi calcolare per esempi con opzioni.

Person.sum(:age) # => 4562 

sembra che il codice dovrebbe essere senza il &:

payments.sum(:price) 
+0

Grazie! Il mio vecchio codice sembra aver funzionato fino a Rails 4.1 ... – Railsana

+1

Questo sembra funzionare solo sui nomi delle colonne - un modo semplice e veloce per farlo con metodi come il sum usato per lavorare? – Sean

+3

@Sean se non usi [rails] (http://api.rubyonrails.org/classes/Enumerable.html#method-i-sum), puoi semplicemente usare il classico ['inject'] (http://ruby-doc.org/core-2.1.2/Enumerable.html#method-i-inject), come questo: 'payments.map (&: price) .inject (: +)' –

0

sum come lo si utilizza è un metodo sul modulo Enumerable definito da Rails, non Ruby. versioni rubino Aggiornamento non dovrebbero fare la differenza:

http://api.rubyonrails.org/classes/Enumerable.html#method-i-sum

Tuttavia, se lo si utilizza per riassumere una colonna su un ActiveRecord mi consiglia di utilizzare sum metodo su ActiveRecord::Relation. Puoi farlo rimuovendo lo &, come suggerito da altre risposte.

http://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-sum

La differenza è che il primo recupera tutti i record dal database, crea gli oggetti, chiama il metodo price su di loro e riassume i risultati. Quest'ultimo crea un'istruzione SQL con SUM, che è molto meglio per le prestazioni.

3

Se aveste eseguire questo in Rails 4.0, si riceverà il seguente avviso deprecazione:

deprecazione ATTENZIONE: Chiamare #SUM con un blocco è deprecato e sarà essere rimosso in Rails 4.1. Se si desidera eseguire il calcolo della somma su della matrice di elementi, utilizzare 'to_a.sum (& blocco)'.

Si riferisce al metodo Relation#sum che precedentemente funzionava in Rails 3.2 quando fornito un blocco.

Come altri hanno risposto, è necessario utilizzare payments.sum(:price) se il prezzo è una colonna di database oppure utilizzare payments.to_a.sum(&:price) se price è un metodo di istanza.