2016-05-01 8 views
1

Ich versuche replicate this mit der Rails-Datenbank (pg) Abfrage, aber nicht viel Glück.Summe aller Beträge, wenn die created_at-Daten in Rails gleich sind

Meine Foo Tabelle hat viele Spalten, aber ich interessiere mich für created_at und amount.

Foo.all.where(client_id: 4) sieht wie folgt aus:

[ 
    [0] {:created_at => <date>, :amount => 20}, 
    [1] {:created_at => <different date>, :amount => 5}, 
    ... 
] 

Stripe Charge Object in json ist so dachte ich, ich könnte:

f = Foo.all.where(client_id: 4).as_json # could I? 

Wie auch immer, mein Controller:

# As per first link above 
def each_user_foo 
    starting_after = nil 
    loop do 
    f = Foo.all.where(client_id: 4).as_json 
    #f_hash = Hash[f.each_slice(2).to_a] # I was trying something here 
    break if f.none? 
    f.each do |bar| 
     yield bar 
    end 
    starting_after = bar.last.id 
    end 
end 

foo_by_date = Hash.new(0) 

each_user_foo do |f| 
    # Parses date object. `to_date` converts a DateTime object to a date (daily resolution). 
    amount_date = DateTime.strptime(f.created_at.to_s, "%s").to_date # line 50 
    amount = f.amount 

    # Initialize the amount for this date to 0. 
    foo_by_date[amount_date] ||= 0 

    foo_by_date[amount_date] += amount 
end 

Mein Fehler bei Linie 50 ist:

nicht definierte Methode `created_at‘ für Hash

Ich denke, ein Objekt irgendwo noch in einem Array ist. Gibt es auch eine Entsprechung für die JS console.log() in Rails? Wäre praktisch.

Antwort

1

Es sieht aus wie f als Hash-Objekt gespeichert wird as_json durch den Aufruf, aber Sie behandeln es wie ein plain-altes Ruby-Objekt in Ihrem each_user_foo Block durch den . Operator.

Die Lösung besteht darin, stattdessen den Hash-Accessor-Operator zu verwenden (z. B. f[:created_at]). Sie brauchen auch nicht stringify und das Datum zu analysieren, weil es bereits ein DateTime Objekt:

amount_date = f[:created_at].to_date # line 50 
amount = f[:amount] 

Auch Foo ist eine Modellklasse richtig? Wenn ja, würde ich empfehlen, pluck mit den Attributen, die Sie brauchen, um zu bekommen, die effizienter sein und sauberer als as_json Aufruf:

# As per first link above 
def each_user_foo 
    f = Foo.where(client_id: 4).pluck(:created_at, :amount) 
    f.each do |bar| 
     yield(bar.first, bar.last) 
    end 
end 

foo_by_date = Hash.new(0) 

each_user_foo do |created_at, amount| 
    # Parses date object. `to_date` converts a DateTime object to a date (daily resolution). 
    amount_date = created_at.to_date # line 50 
    foo_by_date[amount_date] += amount 
end 

Sie können diese Linie auch entfernen:

foo_by_date[amount_date] ||= 0 

Seit Sie verwenden einen Initialisierer in Ihrer foo_by_date = Hash.new(0) Variablenzuweisung).

EDIT

Wenn Sie Postgres verwenden, tun gerade:

Foo.where(client_id: 4).group("date_trunc('day', created_at)").sum(:amount) 

Oder für MySQL:

Foo.where(client_id: 4).group("DAY(created_at)").sum(:amount) 

Viel, viel einfacher als die aktuelle Ansatz.

Das Äquivalent von console.log() in Rails ist Rails.logger.info(), Sie können auch Rails.logger.warn() und Rails.logger.error() verwenden.Wirklich, jede Funktion, die an STDOUT, wie puts und print ausgibt, wird auf Ihrer Konsole ausgegeben.

+0

Ahh danke. Ich bekomme jetzt eine undefinierte Methode '[] 'für Sun, 01 May 2016 07:07:35 UTC +00: 00: Zeit, wenn ich' pluck' benutze. – Sylar

+0

In der gleichen Zeile wie Ihr erster Fehler? –

+0

Lassen Sie mich alles doppelt überprüfen. – Sylar

Verwandte Themen