Reputation: 125882
I'm using the PDFKit middleware to render PDFs. Here's what it does:
Generally, I want that behavior. But I have one case where I actually need my app to render different content based on the fact that a PDF was requested.
PDFKit provides me a marker to detect that it is planning to render my response: it sets env["Rack-Middleware-PDFKit"]
to be true.
But I need to tell Rails that, based on that flag, I want it to render show.pdf.haml
. How can I do that?
Upvotes: 4
Views: 1915
Reputation: 125882
Figured it out. According to the Rails source, request.format = 'pdf'
will manually set the response format to PDF. This means that Rails will render, for example, show.pdf.haml
.
However, now PDFKit will not convert the response to an actual PDF, because the Content-Type
header says it's already PDF, when we're actually only generating HTML. So we also need to override the Rails' response header to say that it's still HTML.
This controller method handles it:
# By default, when PDF format is requested, PDFKit's middleware asks the app
# to respond with HTML. If we actually need to generate different HTML based
# on the fact that a PDF was requested, this method reverts us back to the
# normal Rails `respond_to` for PDF.
def use_pdf_specific_template
return unless env['Rack-Middleware-PDFKit']
# Tell the controller that the request is for PDF so it
# will use a PDF-specific template
request.format = 'pdf'
# Tell PDFKit that the response is HTML so it will convert to PDF
response.headers['Content-Type'] = 'text/html'
end
Which means the controller action looks like:
def show
@invoice = Finance::Invoice.get!(params[:id])
# Only call this if PDF responses should not use the same templates as HTML
use_pdf_specific_template
respond_to do |format|
format.html
format.pdf
end
end
Upvotes: 5