当它用于输出多个时,为什么输出一个文档?

时间:2014-04-28 14:58:45

标签: ruby

这用于为列表中的每个人输出文档。但是,因为我添加了代码来确定最受欢迎的日期&对于给定日期列表的时间,它现在只为列表中的第一个人输出一个文档。

def save_thank_you_letters(id,form_letter)
  Dir.mkdir("output") unless Dir.exists?("output")

  filename = "output/thanks_#{id}.html"

  File.open(filename,'w') do |file|
    file.puts form_letter
  end
end

puts "EventManager initialized."

contents = CSV.open 'event_attendees.csv', headers: true, header_converters: :symbol

template_letter = File.read "form_letter.erb"
erb_template = ERB.new template_letter

contents.each do |row|
  id = row[0]
  name = row[:first_name]
  zipcode = clean_zipcode(row[:zipcode])

  phone = clean_phonenumber(row[:homephone])

  legislators = legislators_by_zipcode(zipcode)

  form_letter = erb_template.result(binding)

  save_thank_you_letters(id,form_letter)

# IT WORKS OK UNTIL I ADD THIS PART...
  times = contents.map { |row| row[:regdate] }
  target_times = Hash[times.group_by do |t|
    DateTime.strptime(t, '%m/%d/%y %H:%M').hour
  end.map do |k,v|
    [k, v.count]
  end.sort_by do |k,v|
    v
  end.reverse]

  target_days = Hash[times.group_by do |t|
    DateTime.strptime(t, '%m/%d/%y %H:%M').wday
  end.map do |k,v|
    [Date::ABBR_DAYNAMES[k], v.count]
  end.sort_by do |k,v| 
    v
  end.reverse]
  puts target_times
  puts target_days
end

我认为这与我处理日期/时间数据中的数据的方式有关。如果我删除它,我会为列表中的每个人获取一个html文档。但如果我加入它,我会得到日期&我正在寻找的时间信息 - 但它只为列表中的第一个人生成一个文档。

有人可以解释为什么我在做什么不起作用?我想打印一周的时间和日期,但也为列表中的每个人生成一个html文档。

谢谢!

1 个答案:

答案 0 :(得分:0)

当您读取CSV文件时,您会逐行移动内部指针读取它。一旦你到达文件的末尾,这个指针就会停留在那里,所以每当你尝试获取新行时,除非你回卷文件,否则你将获得nil。所以,你的代码在这一行开始迭代:

contents.each do |row|

这会获取第一行并将光标移动到下一行。但是在循环内你做了contents.map {...},它读取了整个csv文件并将curses保留在文件的末尾。 所以要修复它,你需要在循环之外(之前或之后)移动统计位并在第二次迭代之前倒回文件(重置光标):

contents.each do |row|
  id = row[0]
  name = row[:first_name]
  zipcode = clean_zipcode(row[:zipcode])

  phone = clean_phonenumber(row[:homephone])

  legislators = legislators_by_zipcode(zipcode)

  form_letter = erb_template.result(binding)

  save_thank_you_letters(id,form_letter)

end

contents.rewind
times = contents.map { |row| row[:regdate] }
target_times = Hash[times.group_by do |t|
  DateTime.strptime(t, '%m/%d/%y %H:%M').hour
end.map do |k,v|
  [k, v.count]
end.sort_by do |k,v|
  v
end.reverse]

target_days = Hash[times.group_by do |t|
  DateTime.strptime(t, '%m/%d/%y %H:%M').wday
end.map do |k,v|
  [Date::ABBR_DAYNAMES[k], v.count]
end.sort_by do |k,v| 
  v
end.reverse]
puts target_times
puts target_days