Commit 9f5b4027 authored by James Edwards-Jones's avatar James Edwards-Jones

CSV generated via Tempfile

parent 889a9370
......@@ -10,6 +10,6 @@ class ExportCsvWorker
issues = IssuesFinder.new(@current_user, params.symbolize_keys).execute
Issues::ExportCsvService.new(issues.limit(100)).email(@current_user, @project)
Issues::ExportCsvService.new(issues).email(@current_user, @project)
end
end
......@@ -26,7 +26,7 @@ class CsvBuilder
# Renders the csv to a string
def render
CSV.generate do |csv|
generate_csv_with_tempfile do |csv|
csv << headers
@collection.find_each do |object|
......@@ -38,11 +38,11 @@ class CsvBuilder
private
def headers
@header_to_value_hash.keys
@headers ||= @header_to_value_hash.keys
end
def attributes
@header_to_value_hash.values
@attributes ||= @header_to_value_hash.values
end
def row(object)
......@@ -54,4 +54,17 @@ class CsvBuilder
end
end
end
def generate_csv_with_tempfile
tempfile = Tempfile.new('issues_csv')
csv = CSV.new(tempfile)
yield(csv)
tempfile.rewind
tempfile.read
ensure
tempfile.close
tempfile.unlink
end
end
......@@ -14,6 +14,18 @@ describe CsvBuilder, lib: true do
expect(csv_data.scan(/(,|\n)/).join).to include ",\n,"
end
it 'uses a temporary file to reduce memory allocation' do
expect(CSV).to receive(:new).with(instance_of(Tempfile)).and_call_original
subject.render
end
it 'avoids loading all data in a single query' do
expect(fake_relation).to receive(:find_each)
subject.render
end
it 'uses hash keys as headers' do
expect(csv_data).to start_with 'Q & A'
end
......
......@@ -5,7 +5,6 @@ describe Issues::ExportCsvService, services: true do
let(:project) { create(:empty_project, :public) }
let!(:issue) { create(:issue, project: project, author: user) }
let(:subject) { described_class.new(Issue.all) }
let(:email) { subject.email(user, project) }
it 'renders csv to string' do
expect(subject.render).to be_a String
......@@ -13,15 +12,12 @@ describe Issues::ExportCsvService, services: true do
describe '#email' do
it 'emails csv' do
expect{ email }.to change(ActionMailer::Base.deliveries, :count)
expect{ subject.email(user, project) }.to change(ActionMailer::Base.deliveries, :count)
end
end
it 'renders csv to temporary file'
def csv
attachment = email.attachments[0]
CSV.parse(attachment.decode_body, headers: true)
CSV.parse(subject.render, headers: true)
end
context 'includes' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment