0

次のような配列ハッシュ データを生成するヘルパー モジュールがあります。

[{:date => d, :total_amount => 31, :first_category => 1, :second_category => 2,...},
 {:date => d+1, :total_amount => 31, :first_category => 1, :second_category => 2,...}]

だから私は次のような方法を作ります:

def records_chart_data(category = nil, start = 3.weeks.ago)
  total_by_day = Record.total_grouped_by_day(start)
  category_sum_by_day = Record.sum_of_category_by_day(start)

  (start.to_date..Time.zone.today).map do |date|
    {
      :date  => date,
      :total_amount => total_by_day[date].try(:first).try(:total_amount) || 0,
      Category.find(1).title => category_sum_by_day[0][date].try(:first).try(:total_amount) || 0,
      Category.find(2).title => category_sum_by_day[1][date].try(:first).try(:total_amount) || 0,
      Category.find(3).title => category_sum_by_day[2][date].try(:first).try(:total_amount) || 0,
    }
  end
end

カテゴリは常に変更されるため、次のようにこのメソッドでループを使用しようとします。

def records_chart_data(category = nil, start = 3.weeks.ago)
  total_by_day = Record.total_grouped_by_day(start)
  category_sum_by_day = Record.sum_of_category_by_day(start)

  (start.to_date..Time.zone.today).map do |date|
    {
      :date  => date,
      Category.all.each_with_index do |category, index|             
        category.title => category_sum_by_day[index][date].try(:first).try(:total_amount) || 0,
      end
      :total_amount => total_by_day[date].try(:first).try(:total_amount) || 0
    }
  end
end

しかし、ルビーはエラーで私に警告します:

/Users/tsu/Code/CashNotes/app/helpers/records_helper.rb:10: syntax error, unexpected tASSOC, expecting keyword_end
      category.title => category_sum_by_day[index][d...

と表示されるのはなぜexpecting keyword_endですか? どうすれば修正できますか?


呼び出すメソッドcategory_sum_by_dayは次のようになります。

def self.sum_of_category_by_day(start)
  records = where(date: start.beginning_of_day..Time.zone.today)
  records = records.group('category_id, date(date)')
  records = records.select('category_id, date, sum(amount) as total_amount')
  records = records.group_by{ |r| r.category_id }
  records.map do |category_id, value|
    value.group_by {|r| r.date.to_date} 
  end
end

または、このメソッドを変更して、上記のヘルパーにより使いやすいメソッドを生成する必要がありますか?

4

1 に答える 1

2
Category.all.each_with_index do |category, index|             
  category.title => category_sum_by_day # ...snip!
end

残念ながら、このコードは Ruby の文法に準拠していません。問題はブロックの本体です。x => yは式ではなく、構文ではブロックの本体が式である必要があります。

一度に 1 つのキーと値のペアでハッシュを生成したい場合は、次の と splat 演算子の組み合わせ (つまり unary ) を試しHash::[]Array#flattenください*

Hash[*5.times.map { |i| [i * 3, - i * i] }.flatten]

結果として、多かれ少なかれの最後の式をrecords_chart_data次のように書き直します。

(start.to_date..Time.zone.today).map do |date|
  categories = Hash[*Category.all.each_with_index do |category, index|
    [ category.title, category_sum_by_day[...] ]
  end .flatten]

  { :date  => date,
    :total_amount => total_by_day[date].try(:first).try(:total_amount) || 0
  }.merge categories
end

判読できないと思われる場合は、あまり洗練されていない方法で実行できます。つまり、次のようになります。

(start.to_date..Time.zone.today).map do |date|
  hash = {
    :date  => date,
    :total_amount => total_by_day[date].try(:first).try(:total_amount) || 0
  }
  Category.all.each_with_index do |category, index|
    hash[category.title] = category_sum_by_day[...]
  end
  hash
end

別のアイデアはArray#reduce、より機能的なアプローチを使用して採用することです。

(start.to_date..Time.zone.today).map do |date|
  Category.all.each_with_index.reduce({
    :date  => date,
    :total_amount => total_by_day[date].try(:first).try(:total_amount) || 0
  }) do |hash, (category, index)|
    hash.merge category.title => category_sum_by_day[...]
  end
  hash
end
于 2012-12-17T11:12:27.573 に答える