Ruby 1.8.7, Rails 3.0.4, PDFKit 0.5.0
I'm trying to create a PDF with PDFKit without using the middleware so I can disable javascript (there's an accordion action in there that hides a lot of info that should be on the PDF). However, whenever I try, it fails because it says the partials in my view (show.html.erb) are missing:
Missing partial programs/details with {:locale=>[:en, :en], :formats=>[:pdf], :handlers=>[:erb, :rjs, :builder, :rhtml, :rxml]}
If I remove the references to the partials, it works fine. I've also tried putting the partials in the same directory with show.html.erb to no avail. Here is the code in my controller's show action:
respond_to do |format|
format.html # show.html.erb
format.pdf {
html = render_to_string(:template => "show.html.erb")
kit = PDFKit.new(html, :disable_javascript => true )
send_data(kit.to_pdf, :filename => "test_pdf", :type => "application/pdf", :disposition => 'attachment')
}
end
Is there any way to do this and keep the partials?
EDIT: for now I've done this:
# config/initializers/pdfkit.rb
PDFKit.configure do |config|
config.default_options = {
:page_size => 'Legal',
:print_media_type => true,
:disable_javascript => true
}
end
This has the disadvantage of turning off javascript for every PDF I generate, but it'll do for now. Any answers on the original question of getting the partials to work still with render_to_string still appreciated.
I was running into this issue this morning and came across your question while looking for a solution.
Controller extract:
respond_to do |format|
format.html
format.pdf {
html = render_to_string(:layout => false , :action => "constitution.pdf.haml")
kit = PDFKit.new(html)
kit.stylesheets << "#{Rails.root}/public/stylesheets/pdf.css"
send_data(kit.to_pdf, :filename => "#{#organisation_name} Constitution.pdf",
:type => 'application/pdf', :disposition => 'inline')
return
}
end
constitution.pdf.haml extract:
=render :partial => 'shared/constitution'
Error:
Missing partial shared/constitution with {:locale=>[:en, :e ...
After a while banging my head against a wall, I had a guess and changed constitution.pdf.haml to:
=render :partial => 'shared/constitution.html.haml'
I only know a tiny amount about Rails. Could it really be that (unlike my normal Haml views), PDFKit requires the file extension? That's fixed it for me!
You can also set :formats for render_to_string to prevent having to change your partial names.
html = render_to_string(:layout => false , :action => "show", :formats => :html)
This forces html, instead of pdf, format for the remained of the view rendering. Allowing you to use the same views/partials without change for HTML and PDF responses.
You should specify full path to your template I think:
html = render_to_string(:template => "my_view_folder_name/show.html.erb")
Related
What I want to do is, generate a PDF file from my current page. (HTML)
I call a controller function which generates my page, it fetches data from database and so on.
Now I want a button which saves the current rendered page as a PDF file on the visitors machine. How can I do that?
If I use your code like this:
respond_to do |format|
format.html { render :template => "user/settings" }
format.pdf {
kit = PDFKit.new('http://google.com')
kit.stylesheets << "#{Rails.root}/public/stylesheets/pdf.css"
send_data(kit.to_pdf, :filename=>"sdasd.pdf",
:type => 'application/pdf', :disposition => 'inline')
}
end
and reload the page ... nothing gonna be downloaded as a pdf ... why?
You can create a similar template for pdf of your current page. Then you can use pdfkit gem.
Add this gems to your gemfile:
gem "pdfkit"
gem "wkhtmltopdf-binary"
Add something like this at your controller:
def show
#user= User.find(params[:id])
respond_to do |format|
format.html { render :template => "users/show" }
format.pdf {
html = render_to_string(:layout => false , :action => "show.pdf.erb") # your view erb files goes to :action
kit = PDFKit.new(html)
kit.stylesheets << "#{Rails.root}/public/stylesheets/pdf.css"
send_data(kit.to_pdf, :filename=>"#{#user.id}.pdf",
:type => 'application/pdf', :disposition => 'inline')
}
end
end
Now you can download pdf by adding .pdf to your controller route. eg: controller/routes/path/1.pdf
Or if you don't like it you can do
kit = PDFKit.new('http://google.com')
How to get the xml output of a view/controller as string within the same controler
This is the routes file
routes.rb
map.ccda '/ccda/ccda_patient_search', :controller => 'ccda', :action => :ccda_patient_search
map.ccda '/ccda/:id.:format', :controller => 'ccda', :action => :index
ccda_controller.rb
class CcdaController < ApplicationController
def index
#
# some process
# result = User.find(params[:id]).result
#
#ccda = result
respond_to do |format|
format.xml { render :layout => false, :template=> "index.xml.builder" }
format.any { redirect_to login_url }
end
end
def get_xml
# render_to_string 'index', :layout=>false, :formats=>[:xml], :locals=>{:id=>147} => Not working
# render_to_string '147.xml' => Not working
#
# How do I get the output of 'http://localhost/ccda/147.xml' here???
#
end
end
I will use the url localhost/ccda/147.xml to view/generate the users result as xml
Now I want the output of that url as a string without returning to browser
I've tried to get it from same controller using render_to_string method with diffrent parameters but nothing seems to work
FYI: I am using rails 2.3.12 and Builder::XmlMarkup API
How about using the following call (inside controller, have taken the known options from your question):
render_to_string(:template => 'ccda/index.xml.builder', :layout => false, :id => 147)
Due to the documentation, this will work up to Rails version 2.3.8, so I don't know if it is available any more in Rails 2.3.12 you are using.
PS: How about upgrading to at least last version of Rails 3? I don't have a change to test my solution, so it is guesswork more or less.
How about this below?
render_to_string :controller => 'ccda_controller', :action => 'index', :id => 147, :format => :xml
Finally I've found that we need to specify the view file manually because by default rails will be looking for index.erb so what I've done is this
render_to_string( :action=>"index", :view => "/ccda/index.xml.builder", :format=>:xml,:layout=>false,:id=>146, :template=>"/ccda/index.xml.builder" )
specifying :view and :template manually solved my problem
I installed wicked PDF and modified my controller :
def show
respond_to do |format|
format.pdf do
render :pdf => "file_name"
end
format.html
end
end
Here is how i link to the pdf : compte_contrat_path(c,:format=>'pdf')
It works for html (without the format) but fail for PDF with the following error :
Template is missing
Missing template contrats/show with {:locale=>[:fr], :formats=>[:pdf],
:handlers=>[:erb, :builder, :coffee, :arb]}. Searched in: *
"/home/sylario/ruby/place_de_marche/app/views" *
"/usr/local/rvm/gems/ruby-1.9.2-p136/gems/activeadmin-0.5.0/app/views"
* "/usr/local/rvm/gems/ruby-1.9.2-p136/gems/kaminari-0.14.1/app/views" * "/usr/local/rvm/gems/ruby-1.9.2-p136/gems/devise-2.2.0/app/views"
What am I doing wrong?
Thanks to henry I now know it was related to the format of the ERB.
I have found a way to reuse my html.erb files :
First i do the following in the controller
format.pdf do
render :pdf => "file.pdf", :template => 'contrats/show.html.erb'
end
Then when i use partials i call them like this :
render :partial => 'fullpath/toview.html.erb', :formats => [:html], :locals => { :mylocal=>#something }
For Rails 7, this is what works:
format.pdf do
render pdf: "file_name", template: "posts/show", formats: [:html]
end
Notice that template no longer have .html.erb and don't forget to include 'formats'.
I currently run Rails 3.1 and am using the latest version of Wicked_pdf for PDF generation.
I have set everything up correctly, and PDFs are generated just fine.
However, I want the user to be able to click a button to DOWNLOAD the pdf. At the present time, when clicked, the browser renders the pdf and displays it on the page.
<%= link_to "Download PDF", { :action => "show", :format => :pdf }, class: 'button nice red large radius', target: '_blank'%>
My Controller.
def show
#curric = Curric.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #curric }
format.pdf do
render :pdf => #curric.name + " CV",
:margin => {:top => 20,
:bottom => 20 }
end
end
end
I have been pointed towards send_file, but have absolutely no idea how to use it in this scenario.
Any help is appreciated.
Decomposition the config you need to set as 'attachment', example:
respond_to do |format|
format.pdf do
render pdf: #curric.name + " CV",
disposition: 'attachment'
end
end
I am doing it that way:
def show
#candidate = Candidate.find params[:id]
respond_to do |format|
format.html
format.pdf do
#pdf = render_to_string :pdf => #candidate.cv_filename,
:encoding => "UTF-8"
send_data(#pdf, :filename => #candidate.cv_filename, :type=>"application/pdf")
end
end
end
and it works for me ;-)
Let's try:
pdf = render_to_string :pdf => #curric.name + " CV",
:margin => {:top => 20,
:bottom => 20 }
send_file pdf
//Download pdf generated from html template using wicket_pdf gem
pdf = render_to_string :template => "simple/show" // here show is a show.pdf.erb inside view
send_data pdf
What i have is the controller action responding to html and pdf file format like this:
def detail
#record = Model.find(params[:id])
respond_to do |format|
format.html # detail.html.erb
format.pdf { render :layout => false } #detail.pdf.prawn
end
end
but when i get the file it comes with the name: 1.pdf 2.pdf depending on the params[:id] how do i set the filename to myfile.pdf
--UPDATE--
Example of my detail.pdf.prawn file
pdf.font "Helvetica"
pdf.image open("http://localhost:3000/images/myImage.png"),:position => :left,:width=>100
pdf.text "some text"
pdf.table(someData,:cell_style => { :border_width => 0.1,:border_color=> 'C1C1C1' }) do |table|
table.row(0).style :background_color => 'D3D3D3'
table.column(0..1).style(:align => :left)
table.column(2..4).style(:align => :center)
table.column(0).width = 100
table.column(1).width = 250
table.column(3..4).width = 68
table.row(2).column(0..2).borders = []
table.row(2).column(3).style(:font_style => :bold, :align => :right)
end
and the format.pdf { render :layout => false } in the controller renders de pdf file with the instructions on detail.pdf.prawn
To elaborate on fl00r's answer, If your using prawnto, the pdf setup params can go in your controller, including the filename.
def detail
#record = Model.find(params[:id])
prawnto :prawn => { :page_size => 'A4',
:left_margin => 50,
:right_margin => 50,
:top_margin => 80,
:bottom_margin => 50},
:filename => #record.name, :inline => true #or false
respond_to do |format|
format.html # detail.html.erb
format.pdf { render :layout => false } #detail.pdf.prawn
end
end
If you are creating lot's of different pdf's with prawnto, you would probably move the config out into it's own method. but if your only doing the one, in the controller is fine.
NOTE: the PDF url will still display e.g. 1.pdf But when they save the PDF the filename param will show up in the save box dialog.
prawnto :filename => "myfile", :prawn => {
...
}
Really thanks, this post really help my old pdf way. There is another way to using prawn of Rails. You can check oh this link. Not mine, but a good tutorial for making it. Just saying probably for anyone that still confuse how to make it.
I was using this method before, then I moved on method from that link. Really fun for doing some research about it.
If prawn-rails or prawn_plus you may do following in controller.
headers["Content-Disposition"] = "attachment; filename=\"myfile.pdf\""