Reputation: 105
I am trying to download an HTML view in Rails5 as a PDF, however, whenever I download the PDF I get an error: Failed to load PDF document. I am using the following gems:
gem 'pdf kit' gem 'wkhtmltopdf-binary'
here is my controller:
class InputController < ApplicationController
def index
@inputs = Input.all
end
def show
@input = Input.find_by(id: params[:id])
send_data @pdf, :filename => @input.company + ".pdf",
:type => "application/pdf",
:disposition => "attachment"
end
end
when i type in a download URL ie: localhost:3000/input/1.pdf i get a downloaded pdf file with an error:
My show view is very simple:
<ul>
<li><%= @input.company %></li>
<li><%= @input.position %></li>
<li><%= @input.date %></li>
</ul>
Any help would be appreciated.
Best, Ayaz
UPDATE
I also just tried taking out @pdf and putting in @input:
def show
@input = Input.find_by(id: params[:id])
send_data @input, :filename => @input.company + ".pdf",
:type => "application/pdf",
:disposition => "attachment"
end
No change in results
Upvotes: 0
Views: 1760
Reputation: 48599
Your code doesn't assign anything to the instance variable @pdf
:
def show
@input = Input.find_by(id: params[:id])
send_data @pdf, :filename => @input.company + ".pdf",
:type => "application/pdf",
:disposition => "attachment"
end
and instance variables have a default value of nil
. You need to do something like:
input = Input.find_by(id: params[:id])
html = %Q{
<ul>
<li>#{input.company}</li>
<li>#{input.position}</li>
<li>#{input.date}</li>
</ul>
}
kit = PDFKit.new(html, :page_size => 'Letter')
pdf = kit.to_pdf
send_data pdf, :filename => input.company + ".pdf",
:type => "application/pdf",
:disposition => "attachment"
Or, if you want to read the view file then run it through the ERB engine, something like this:
file_path = File.expand_path("../views/input/show.html.erb", __FILE__)
erb_template = File.read(file_path)
@input = Input.find_by(id: params[:id])
renderer = ERB.new(erb_template)
html = renderer.result()
#As above...
From the Rails Guide:
By default, controllers in Rails automatically render views with names that correspond to valid routes.
...
...
The rule is that if you do not explicitly render something at the end of a controller action, Rails will automatically look for the action_name.html.erb template in the controller's view path and render it.
And from the docs for send_data():
This method is similar to
render plain: data
, but also allows you to specify whether the browser should display the response as a file attachment (i.e. in a download dialog) or as inline data
Therefore, when you call send_data()
in the controller, you are explicitly rendering something, so the default rendering of the action_name.html.erb file doesn't occur.
Upvotes: 3