Commit 76107fc0 authored by James Edwards-Jones's avatar James Edwards-Jones

Truncated CSV exports include count of issues included

parent 44969774
......@@ -49,10 +49,11 @@ module Emails
mail_answer_thread(issue, issue_thread_options(updated_by_user.id, recipient.id))
end
def issues_csv_email(user, project, csv_data, issues_count, truncated = false)
def issues_csv_email(user, project, csv_data, export_status)
@project = project
@issues_count = issues_count
@truncated = truncated
@issues_count = export_status.fetch(:rows_expected)
@written_count = export_status.fetch(:rows_written)
@truncated = export_status.fetch(:truncated)
filename = "#{project.full_path.parameterize}_issues_#{Date.today.iso8601}.csv"
attachments[filename] = { content: csv_data, mime_type: 'text/csv' }
......
......@@ -16,7 +16,7 @@ module Issues
end
def email(user, project)
Notify.issues_csv_email(user, project, csv_data, @issues.count, csv_builder.truncated?).deliver_now
Notify.issues_csv_email(user, project, csv_data, csv_builder.status).deliver_now
end
def csv_builder
......
%span{ style: 'font-size:18px;'}
Your CSV export of #{ @issues_count } issues from project
Your CSV export of #{ @written_count } issues from project
%a{ href: project_url(@project), style: "color:#3777b0;text-decoration:none;" }
= @project.full_name
has been added to this email as an attachment.
- if @truncated
%p
This attachment has been truncated due to exceeding the maximum attachment size. Consider re-exporting with a narrower selection of issues.
This attachment has been truncated to avoid exceeding a maximum allowed attachment size of 20MB. #{ @written_count } of #{ @issues_count } issues have been included. Consider re-exporting with a narrower selection of issues.
Your CSV export of <%= @issues_count %> issues from project <%= @project.full_name %> ( <%= project_url(@project) %> ) has been added to this email as an attachment.
Your CSV export of <%= @written_count %> issues from project <%= @project.full_name %> ( <%= project_url(@project) %> ) has been added to this email as an attachment.
<% if @truncated %>
This attachment has been truncated due to exceeding the maximum attachment size. Consider re-exporting with a narrower selection of issues.
This attachment has been truncated to avoid exceeding a maximum allowed attachment size of 20MB. <%= @written_count %> of <%= @issues_count %> issues have been included. Consider re-exporting with a narrower selection of issues.
<% end %>
\ No newline at end of file
......@@ -23,6 +23,7 @@ class CsvBuilder
@header_to_value_hash = header_to_value_hash
@collection = collection
@truncated = false
@rows_written = 0
end
# Renders the csv to a string
......@@ -45,6 +46,26 @@ class CsvBuilder
@truncated
end
def rows_written
@rows_written
end
def rows_expected
if truncated? || rows_written == 0
@collection.count
else
rows_written
end
end
def status
{
truncated: truncated?,
rows_written: rows_written,
rows_expected: rows_expected
}
end
private
def headers
......@@ -71,6 +92,8 @@ class CsvBuilder
@collection.find_each do |object|
csv << row(object)
@rows_written += 1
if until_block.call
@truncated = true
break
......
......@@ -2,12 +2,14 @@ require 'spec_helper'
describe CsvBuilder, lib: true do
let(:object) { double(question: :answer) }
let(:fake_relation) { [object] }
let(:fake_relation) { FakeRelation.new([object]) }
let(:subject) { CsvBuilder.new(fake_relation, 'Q & A' => :question, 'Reversed' => -> (o) { o.question.to_s.reverse }) }
let(:csv_data) { subject.render }
before do
allow(fake_relation).to receive(:find_each).and_yield(object)
class FakeRelation < Array
def find_each(&block)
each(&block)
end
end
it 'generates a csv' do
......@@ -20,23 +22,46 @@ describe CsvBuilder, lib: true do
subject.render
end
it 'counts the number of rows' do
subject.render
expect(subject.rows_written).to eq 1
end
describe 'rows_expected' do
it 'uses rows_written if CSV rendered successfully' do
subject.render
expect(fake_relation).not_to receive(:count)
expect(subject.rows_expected).to eq 1
end
it 'falls back to calling .count before rendering begins' do
expect(subject.rows_expected).to eq 1
end
end
describe 'truncation' do
let(:big_object) { double(question: 'Long' * 1024) }
let(:row_size) { big_object.question.length * 2 }
let(:fake_relation) { FakeRelation.new([big_object, big_object, big_object]) }
before do
allow(fake_relation).to receive(:find_each).and_yield(big_object)
.and_yield(big_object)
.and_yield(big_object)
end
it 'after given number of bytes' do
it 'occurs after given number of bytes' do
expect(subject.render(row_size * 2).length).to be_between(row_size * 2, row_size * 3)
expect(subject).to be_truncated
expect(subject.rows_written).to eq 2
end
it 'is ignored by default' do
expect(subject.render.length).to be > row_size * 3
expect(subject.rows_written).to eq 3
end
it 'causes rows_expected to fall back to .count' do
subject.render(0)
expect(fake_relation).to receive(:count).and_call_original
expect(subject.rows_expected).to eq 3
end
end
......
......@@ -8,8 +8,8 @@ describe Notify do
describe 'csv export email' do
let(:user) { create(:user) }
let(:empty_project) { create(:empty_project, path: 'myproject') }
let(:truncated) { false }
subject { Notify.issues_csv_email(user, empty_project, "dummy content", 3, truncated) }
let(:export_status) { { truncated: false, rows_expected: 3, rows_written: 3 } }
subject { Notify.issues_csv_email(user, empty_project, "dummy content", export_status) }
let(:attachment) { subject.attachments.first }
it 'attachment has csv mime type' do
......@@ -33,11 +33,15 @@ describe Notify do
end
context 'when truncated' do
let(:truncated) { true }
let(:export_status) { { truncated: true, rows_expected: 12, rows_written: 10 } }
it 'mentions that the csv has been truncated' do
expect(subject).to have_content 'truncated'
end
it 'mentions the number of issues written and expected' do
expect(subject).to have_content '10 of 12 issues'
end
end
end
end
......@@ -2,8 +2,17 @@ class IssuesCsvMailerPreview < ActionMailer::Preview
def issues_csv_export
user = OpenStruct.new(notification_email: 'a@example.com')
project = Project.unscoped.first
issues_count = 891
Notify.issues_csv_email(user, project, "Dummy,Csv\n0,1", issues_count, [true, false].sample)
Notify.issues_csv_email(user, project, "Dummy,Csv\n0,1", export_status)
end
private
def export_status
{
truncated: [true, false].sample,
rows_written: 632,
rows_expected: 891
}
end
end
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