Reputation: 126
I have a Ruby on Rails application which generates PDFs and saves them into /pdf/.. then runs a delayed job to email the pdf to someone. Production is hosted on Heroku.
The process works fine locally, and has in the past worked in the (same) production environment. However, the files are now not generating/saving on the production environment and I have been unable to work out why. Despite going back over all the old commits, I can't see what I have changed to stop the files from generating.
The folder /pdf exists in the root of the application. I have confirmed using Heroku Bash.
I believe the problem to be somewhere around the save_to_file: instruction.
The delayed job is working fine, if I point the attachment to a file that already exists it will execute and send the email.
I am aware that heroku's filesystem does not persist assets. However seeing as I don't want the assets to persist I don't believe this is a problem (I could be wrong), I just want to generate and then use and discard.
My Route:
get '/matrices/:matrix_id/submissions/:id/email' => 'submissions#emailpdf', as: :submissions_emailpdf
My controller:
def emailpdf
get_submission_details
get_topline_stats
get_brand
render javascript_delay: 2000,
pdf: 'submission',
layout: 'pdf',
template: 'submissions/showpdf.html.haml',
show_as_html: params.key?('debug'),
save_to_file: Rails.root.join('pdf', "submission#{@user.id}.pdf"),
save_only: true
SendpdfJob.delay.perform_later(@user.name, @user.id, @user.email, @matrix.id, @submission.id)
redirect_to matrix_submission_path(@matrix,@submission), notice: "We have emailed you your PDF"
end
My delayed job
class SendpdfJob < ActiveJob::Base
queue_as :default
def perform(username, userid, useremail, matrixid, submissionid)
Pony.delay.mail(
:to => useremail,
:from => '[email protected]',
:subject => 'Your Matrix',
:html_body => '<h2>Hello '+ username+'.</h2>
<p> Your Maturity Matrix is attached. We hope you find this useful.
<p >All the best
:attachments => {
"matrix.pdf" => File.read("pdf/submission#{userid}.pdf")
}
);
end
end
My Log errror:
Job SendpdfJob.perform_later (id=45) FAILED (8 prior attempts) with Errno::ENOENT: No such file or directory @ rb_sysopen - pdf/submission26.pdf
Heroku bash confirms there are no files in /pdf
Thanks all very much in advance.
TB
Upvotes: 1
Views: 331
Reputation: 600
As @timpwbaker notes, Heroku doesn't persist files. You can build the file in the tmp directory and do something with it immediately, or you can upload to S3 if it needs to persist. In my worker, I do something along these lines (Heroku/S3 with carrierwave uploader) "issueable" [sic] is my app object.
# Wicked PDF generation code here
# Give it a name and tell it where to write (tmp)
save_location = Rails.root.join("tmp", "#{issueable.name.parameterize}_checklist.pdf")
# Write the PDF to the temp file
File.open(save_location, "wb") do |file|
file << pdf
end
# Create a new uploader to put the file on S3, most stuff defined in uploader
issueable.checklist = ChecklistUploader.new
File.open(save_location, "r") do |file|
issueable.checklist.store!(file)
end
issueable.save!
And here's the checklist uploader for reference.
class ChecklistUploader < CarrierWave::Uploader::Base
storage :fog
def store_dir
"uploads/#{model.class.to_s.underscore}_checklists/#{mounted_as}/#{model.combined}"
end
def extension_whitelist
%w[pdf]
end
end
Upvotes: 2