Add report download link to email notification

I added a system spec to verify that the download link can be generated
within the mailer in a background job. ActiveStorage is a bit particular
when it comes to genererating URLs and depending on the situation it may
generate a redirect URL, a proxy URL or link directly to the storage.
But we want a redirect URL here.
This commit is contained in:
Maikel Linke
2023-04-21 11:47:33 +10:00
committed by Konrad
parent cf5a8a26ce
commit 860fe85af9
7 changed files with 70 additions and 6 deletions

View File

@@ -13,10 +13,13 @@ class ReportJob < ApplicationJob
execution_time = Time.zone.now - start_time
email_result if execution_time > NOTIFICATION_TIME
email_result(user, blob) if execution_time > NOTIFICATION_TIME
end
def email_result
ReportMailer.report_ready.deliver_later
def email_result(user, blob)
ReportMailer.with(
to: user.email,
blob: blob,
).report_ready.deliver_later
end
end

View File

@@ -2,6 +2,11 @@
class ReportMailer < ApplicationMailer
def report_ready
mail
# When we are in a background job then we don't have an HTTP request object
# and we need to tell ActiveStorage the hostname to generate URLs.
ActiveStorage::Current.url_options ||= url_options
@blob = params[:blob]
mail(params)
end
end

View File

@@ -1 +1,5 @@
%h3 TBC
%h3= t(".heading")
%p
= t(".intro")
%ul
%li= link_to(t(".link_label", name: @blob.filename), @blob.url)

View File

@@ -319,6 +319,13 @@ en:
order_cycle:
subject: "Order cycle report for %{producer}"
provider_settings: "Provider settings"
report_mailer:
report_ready:
subject: "Report ready"
heading: "Report ready for download"
intro: |
The link below will expire after one month.
link_label: "%{name}"
shipment_mailer:
shipped_email:
dear_customer: "Dear Customer,"

View File

@@ -40,7 +40,13 @@ describe ReportJob do
# rspec-rails: https://github.com/rspec/rspec-rails/issues/2668
ReportJob.perform_later(*report_args)
perform_enqueued_jobs(only: ReportJob)
}.to enqueue_mail(ReportMailer, :report_ready)
}.to enqueue_mail(ReportMailer, :report_ready).with(
params: {
to: user.email,
blob: blob,
},
args: [],
)
end
it "triggers no email when the report is done quickly" do

View File

@@ -0,0 +1,31 @@
# frozen_string_literal: true
require 'spec_helper'
describe ReportMailer do
describe "#report_ready" do
subject(:email) {
ReportMailer.with(
to: "current_user@example.net",
blob: blob,
).report_ready
}
let(:blob) { ReportBlob.create_for_upload_later!("customers.csv") }
it "notifies about a report" do
expect(email.subject).to eq "Report ready"
expect(email.body).to have_content "Report ready for download"
end
it "notifies the user" do
expect(email.to).to eq ["current_user@example.net"]
end
it "contains a download link" do
expect(email.body).to have_link(
"customers.csv",
href: %r"^http://test\.host/rails/active_storage/disk/.*/customers\.csv$"
)
end
end
end

View File

@@ -77,8 +77,10 @@ describe '
visit admin_report_path(
report_type: :customers, report_subtype: :mailing_list
)
allow(ENV).to receive(:fetch).and_call_original
expect(ENV).to receive(:fetch).with("RACK_TIMEOUT_SERVICE_TIMEOUT", "15")
.and_return("-1") # Negative values time out immediately.
stub_const("ReportJob::NOTIFICATION_TIME", 0)
click_button "Go"
@@ -92,6 +94,12 @@ describe '
content = File.read(downloaded_filename)
expect(content).to match "<th>\nFirst Name\n</th>"
# We also get an email.
perform_enqueued_jobs(only: ActionMailer::MailDeliveryJob)
email = ActionMailer::Base.deliveries.last
expect(email.body).to have_link "customers",
href: %r"^http://test\.host/rails/active_storage/disk/.*/customers_[0-9]+\.html$"
end
end