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

但是 ruby​​ 警告我一个错误:

/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不是表达式,语法要求块的主体是表达式

如果您想一次通过一个键值对生成哈希,请尝试以下组合Hash::[],Array#flatten和 splat 运算符(即一元*):

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 回答