I think this each_with_index block could use some refactoring.

First, unless I am reading this wrong, the current score from the wrong submission gets added to the row (Student i gets Student i+1's score).  Also, there is a small bug where if different users have different numbers of peer_reviews, the current_score value won't always be in the right column.

Additionally, pushing the row into the csv in a different loop iteration than it gets built makes the code more difficult to read and reason about, and requires the hack to handle the last line.

I'm wondering if maybe Enumerable#group_by would help here (http://www.ruby-doc.org/core-1.9.3/Enumerable.html#method-i-group_by).  We could group peer reviews by user_id, and then have an inner loop that adds all the scores to the csv (plus any padding that we need to get up to max_reviews).

Another thought I had that might help make some of the logic simpler, would be to move the "Current Score" column up into the first group of columns, so that you don't have to add any extra padding for rows that have less than max_reviews # of reviews.