Commit 67fbf37f19aa9fe470fc286fe048517e2d26ab44
1 parent
bed4d517
Exists in
master
and in
1 other branch
let FasterCSV do proper CSV escaping for strings
in ideas export CSV let FasterCSV handle the CSV escaping of strings (strings with commas, quotes, newlines, etc.)
Showing
2 changed files
with
75 additions
and
1 deletions
Show diff stats
app/models/question.rb
@@ -556,7 +556,7 @@ class Question < ActiveRecord::Base | @@ -556,7 +556,7 @@ class Question < ActiveRecord::Base | ||
556 | 556 | ||
557 | num_skips = self.skips.count(:conditions => {:prompt_id => left_prompts_ids + right_prompts_ids}) | 557 | num_skips = self.skips.count(:conditions => {:prompt_id => left_prompts_ids + right_prompts_ids}) |
558 | 558 | ||
559 | - csv << [c.question_id, c.id, "'#{c.data.strip}'", c.wins, c.losses, num_skips, c.score, user_submitted , c.creator_id, c.created_at, c.updated_at, active, left_appearances, right_appearances] | 559 | + csv << [c.question_id, c.id, c.data.strip, c.wins, c.losses, num_skips, c.score, user_submitted , c.creator_id, c.created_at, c.updated_at, active, left_appearances, right_appearances] |
560 | 560 | ||
561 | end | 561 | end |
562 | when 'non_votes' | 562 | when 'non_votes' |
spec/models/question_spec.rb
@@ -423,4 +423,78 @@ describe Question do | @@ -423,4 +423,78 @@ describe Question do | ||
423 | after(:all) { truncate_all } | 423 | after(:all) { truncate_all } |
424 | end | 424 | end |
425 | 425 | ||
426 | + context "exporting data with odd characters" do | ||
427 | + before(:all) do | ||
428 | + @aoi_question = Factory.create(:question) | ||
429 | + user = @aoi_question.site | ||
430 | + | ||
431 | + @aoi_question.it_should_autoactivate_ideas = true | ||
432 | + @aoi_question.save! | ||
433 | + | ||
434 | + visitor = user.visitors.find_or_create_by_identifier('visitor identifier') | ||
435 | + | ||
436 | + user.create_choice(visitor.identifier, @aoi_question, | ||
437 | + {:data => "foo\nbar", :local_identifier => "example creator"}) | ||
438 | + user.create_choice(visitor.identifier, @aoi_question, | ||
439 | + {:data => "foo,bar", :local_identifier => "example creator"}) | ||
440 | + user.create_choice(visitor.identifier, @aoi_question, | ||
441 | + {:data => "foo\"bar", :local_identifier => "example creator"}) | ||
442 | + user.create_choice(visitor.identifier, @aoi_question, | ||
443 | + {:data => "foo'bar", :local_identifier => "example creator"}) | ||
444 | + | ||
445 | + 40.times.each do |num| | ||
446 | + @p = @aoi_question.picked_prompt | ||
447 | + | ||
448 | + @a = user.record_appearance(visitor, @p) | ||
449 | + | ||
450 | + vote_options = {:visitor_identifier => visitor.identifier, | ||
451 | + :appearance_lookup => @a.lookup, | ||
452 | + :prompt => @p, | ||
453 | + :time_viewed => rand(1000), | ||
454 | + :direction => (rand(2) == 0) ? "left" : "right" | ||
455 | + } | ||
456 | + | ||
457 | + skip_options = {:visitor_identifier => visitor.identifier, | ||
458 | + :appearance_lookup => @a.lookup, | ||
459 | + :prompt => @p, | ||
460 | + :time_viewed => rand(1000), | ||
461 | + :skip_reason => "some reason" | ||
462 | + } | ||
463 | + | ||
464 | + choice = rand(3) | ||
465 | + case choice | ||
466 | + when 0 | ||
467 | + user.record_vote(vote_options) | ||
468 | + when 1 | ||
469 | + user.record_skip(skip_options) | ||
470 | + when 2 | ||
471 | + #this is an orphaned appearance, so do nothing | ||
472 | + end | ||
473 | + end | ||
474 | + end | ||
475 | + | ||
476 | + it "should export idea data to a csv file" do | ||
477 | + filename = @aoi_question.export('ideas') | ||
478 | + | ||
479 | + filename.should_not be nil | ||
480 | + filename.should match /.*ideamarketplace_#{@aoi_question.id}_ideas[.]csv$/ | ||
481 | + File.exists?(filename).should be_true | ||
482 | + # Not specifying exact file syntax, it's likely to change frequently | ||
483 | + # | ||
484 | + rows = FasterCSV.read(filename) | ||
485 | + rows.first.should include("Idea ID") | ||
486 | + rows.first.should_not include("Skip ID") | ||
487 | + | ||
488 | + rows.shift | ||
489 | + rows.each do |row| | ||
490 | + row[2].should =~ /^foo.bar$/m | ||
491 | + end | ||
492 | + | ||
493 | + #File.delete(filename).should_not be_nil | ||
494 | + | ||
495 | + end | ||
496 | + | ||
497 | + after(:all) { truncate_all } | ||
498 | + end | ||
499 | + | ||
426 | end | 500 | end |