0

重複の可能性:
LazyHighChartsで使用するRailsActiveRecord group_by&sumdbの結果

私はRoR/Rubyにまったく慣れておらず、Lazy High Charts gemを使用して、データベース情報に基づいていくつかのpurdyチャートを生成しています。

私は提供された答えを試しましたが、これを行う方法についてはまだ少し混乱しています。

amount_used、billed_amountを合計し、月/年ごとにグループ化する必要があります(例:2012年8月)

最終結果は、「使用量」と「コスト」の2つのシリーズを持つ2軸グラフに似たものになります。この情報は、特定のaccount_idに固有です。

ここに画像の説明を入力してください

請求書テーブル

+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| id            | int(11)      | NO   | PRI | NULL    | auto_increment |
| account_id    | int(11)      | YES  |     | NULL    |                |
| invoice_date  | varchar(255) | YES  |     | NULL    |                |
| amount_used   | float        | YES  |     | NULL    |                |
| billed_amount | float        | YES  |     | NULL    |                |
| comments      | text         | YES  |     | NULL    |                |
| created_at    | datetime     | NO   |     | NULL    |                |
| updated_at    | datetime     | NO   |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+

コントローラチャートコード

@account = Account.find(params[:id])
@invoices = Invoice.where("account_id = #{@account.id}").order("invoice_date DESC")

@h = LazyHighCharts::HighChart.new('area') do |f|
  f.options[:chart][:defaultSeriesType] = "area"
  #Sample dates right now, should be the grouped_by :invoice_date
  f.xAxis( :categories => ['May', 'Jun', 'Jul'] )
  f.yAxis([
    {
      :title => { :text => "Amount Used" }
    },
    {
      :title => { :text => "Cost" },
      :opposite => true
    }
  ])
  #Sample data right now, should be the summed amounts of the :amount_used correpsonding for each above grouped invoice_date
  f.series(:name => "Amount Used", :data => [100,300,500] )
  #Sample data right now, should be the summed amounts of the :billed_amount correpsonding for each above grouped invoice date
  f.series(:name => "Cost", :yAxis => 1, :data => [200,400,600] )
end 
4

2 に答える 2

3

重要なのはEnumerable#group_by、同じ月のすべての行を検索し、それらを合計するために使用することです。

require 'date'

# Simulate rows from your DB
Row = Struct.new(:date,:amount)
rows = DATA.read.scan(/(\S+) - (\d+)/).map do |date,amount|
    Row.new( Date.strptime(date,'%m/%d/%y'), amount.to_i )
end

sum_by_month = rows.sort_by(&:date).group_by do |row|
    row.date.strftime('%b/%Y')
end.map do |year_and_month,sub_rows|
    [ year_and_month, sub_rows.map(&:amount).inject(:+) ]
end

p sum_by_month
#=> [
#=>   ["Aug/2012", 22000],
#=>   ["Sep/2012", 5000],
#=>   ["Oct/2012", 76000]
#=> ]

__END__
08/01/12 - 10000
08/16/12 - 12000
09/13/12 - 5000
10/12/12 - 76000

特定のユースケースでは、次のように使用できます。

<table><thead><tr><td></td>
  <%sum_by_month.each do |month,total|%>
    <th scope="col"><%=month%></th>
  <%end%>
</thead><tbody>
  <tr><th>Usage:</th>
  <%sum_by_month.each do |month,total|%>
    <td><%=total%></td>
  <%end%></tr>
</tbody></table>

または、より直接的なアプローチを次に示します(これはお勧めしません)。

sum_by_month = {}
last_month = nil
total      = nil
@invoices.each do |inv|
  month = inv.date.strftime('%b/%Y')
  unless last_month==month
    sum_by_month[month] = total if last_month
    last_month = month
    total      = 0
  end
  total += inv.amount
end

# Make sure to add in the very last month
sum_by_month[month] = total if last_month
于 2012-09-07T19:42:43.480 に答える
2

追加情報をありがとう。これをすべてグループ化して、レコードを何度もループすることなくテーブルなどを作成できるはずです。

<% @invoices.group_by { |invoice| DateTime.strptime(invoice.invoice_date.to_s, '%m/%d/%y').strftime('%b/%Y') } do |day, invoices| %>
(@day_headings ||= []) << day  # make an array of your day/year table headings
(@day_counts ||= []) << invoices.sum(&:amount_used) # sum all the invoices amount_used, grouped under this heading
<% end %>

...これで2つの変数ができたので、テーブルを作成できます

<table>
 <thead>
  <tr>
   <% @day_headings.each do |th| %>
    <th><%= th %></th>
   <% end %>
  </tr>
 </thead>
 <tbody>
  <tr>
   <th scope="row">Usage</th>
   <% @day_counts.each do |td| %>
    <td><%= td %></td>
   <% end %>
  </tr>
 </tbody>
</table>

これらのメソッドのドキュメントは次のとおりです:http://api.rubyonrails.org/classes/Enumerable.html

于 2012-09-07T20:00:57.383 に答える