Wicked_pdf page width in multipage pdf - ruby-on-rails

Cheers! I'm using wicked_pdf to generate pdf docs from views:
pdf = WickedPdf.new.pdf_from_string(
render_to_string(
:layout => "pdf_report.haml",
:handlers => [:haml],
:formats => [:pdf, :haml],
:orientation => 'Landscape',
:encoding => "utf8",
:page_width => '2000',
:dpi => '300'
)
)
It's all ok, if pdf has one page:
But if pdf doc has more than one page, then width of the page is broken:

I wasn't able to reproduce your "only has one page" scenario with the code you posted, however there is a problem with the options you are passing. They aren't even getting to wkhtmltopdf, so it is probably deciding for you what kind of options to use.
render_to_string will silently discard any options it doesn't understand, but is not part of wicked_pdf.
pdf_from_string takes two params, the first being the string to pdf-ify, the second is a hash of pdf options from the README.
I've added your issue to the wicked_pdf_issues project here to reproduce and debug it:
https://github.com/unixmonkey/wicked_pdf_issues/commit/b722e8a06c42e1f2bcbb98281915d1e94b4fe2c9
You should get the results you are looking for by changing your code to something like this:
string = render_to_string(
template: 'pages/issue_330',
formats: [:pdf],
handlers: [:erb]
)
options = {
orientation: 'Landscape',
page_width: '2000',
dpi: '300'
}
pdf = WickedPdf.new.pdf_from_string(string, options)

Related

Rails render_to_string using wrong format

I am encountering a problem with render_to_string using Rails 3.2.18 in which the function is trying to render the wrong view format despite its :formats option being correctly set (so for example rendering the kml view when :formats is set to text).
TL-DR version :
If I call render_to_string('foos/bar', formats: 'text', layout: false) and then render_to_string('foos/bar', formats: 'json', layout: false), the later renders bar.text instead of bar.json
Long version :
I have a FoosControler that uses render_to_text when its bar action is called. bar can respond to three formats : text, json and kml. Under my views, I have the three corresponding files bar.text.erb, bar.json.erb and bar.kml.erb. I also have three different tests, in which the controller is instantiated and the output of bar is tested for the different formats (so I am calling FoosControler.new.bar(format)).
If I run each of those tests independently, I have no problems at all. So :
render_to_string('foos/bar', formats: 'text', layout: false)
# => renders bar.text.erb
render_to_string('foos/bar', formats: 'json', layout: false)
# => renders bar.json.erb
render_to_string('foos/bar', formats: 'kml', layout: false)
# => renders bar.kml.erb
The problems start if I have more than one of these in my test suite. What happens is the following :
render_to_string('foos/bar', formats: 'json', layout: false)
# => renders bar.json.erb
render_to_string('foos/bar', formats: 'text', layout: false)
# => renders bar.text.erb
render_to_string('foos/bar', formats: 'json', layout: false)
# => renders bar.text.erb instead of bar.json.erb !
From the moment I rendered bar.text.erb, any call to render_to_string with the json format renders bar.text.erb instead of bar.json.erb like it is supposed to.
The same happens between kml and txt :
render_to_string('foos/bar', formats: 'text', layout: false)
# => renders bar.text.erb
render_to_string('foos/bar', formats: 'kml', layout: false)
# => renders bar.kml.erb
render_to_string('foos/bar', formats: 'text', layout: false)
# => renders bar.kml.erb instead of bar.text.erb !
I can't seem to understand why this problem happens, as the problem isn't linked to the views - they all exist and can be rendered as shown before. Even stranger, everything works if I force the format in the render instead of using the :format parameter :
render_to_string('foos/bar.text', layout: false)
# => renders bar.text.erb
render_to_string('foos/bar.kml', layout: false)
# => renders bar.kml.erb
render_to_string('foos/bar.text', layout: false)
# => renders bar.text.erb like it is supposed to
A few other precisions :
- It doesn't matter whether I use formats: '<format>' or formats: ['<format>']
- The problem happens regardless of whether I use the different render_to_string inside the same controller using a breakpoint or whether I simply call the sequence of FoosController.new.bar(format) in the test, so the following two give the same result :
FoosController.new.bar
render_to_string('foos/bar', formats: 'kml', layout: false)
# => renders bar.kml.erb
render_to_string('foos/bar', formats: 'text', layout: false)
# => renders bar.kml.erb instead of bar.text.erb !
FoosController.new.bar('kml')
# => renders bar.kml.erb
FoosController.new.bar('text')
# => renders bar.kml.erb instead of bar.text.erb !
Any idea what can cause this unwanted behavior ? Forcing the format like I did seems to patch the issue, but I'd still want to know what exactly is going on.
Change your format option from this:
render_to_string('foos/bar', formats: 'text', layout: false)
# => renders bar.text.erb
render_to_string('foos/bar', formats: 'kml', layout: false)
# => renders bar.kml.erb
render_to_string('foos/bar', formats: 'text', layout: false)
# => renders bar.kml.erb instead of bar.text.erb !
To this:
render_to_string('foos/bar', :formats => [:text], layout: false)
render_to_string('foos/bar', :formats => [:kml], layout: false)
render_to_string('foos/bar', :formats => [:text], layout: false)

Rails 4, How to add an s3 image to wicked pdf

In rails 4, I am using wicked_pdf gem for .pdf file download. I have to add an image inside this pdf, right now image is rendering through wicked_pdf_image_tag in development but in test environment image(s3) is not rendering.
Used Gems are,
gem 'wicked_pdf', '1.0.3'
gem 'wkhtmltopdf-binary', '0.9.9.3'
In initializers,
class WickedPdf
wkhtmltopdf_path = Rails.env.production? ? "#{Rails.root}/bin/wkhtmltopdf-amd64" : "#{Rails.root}/bin/wkhtmltopdf-amd64"
WICKED_PDF = {
:exe_path => wkhtmltopdf_path,
:wkhtmltopdf => wkhtmltopdf_path
}
end
In controller,
respond_to do |format|
format.html {
render :pdf => "sample",
:margin => {:top => 10, :bottom => 10, :left => 10, :right => 10},
:orientation => 'Portrait', # default , Landscape,
:no_background => true
}
end
In views, I have tried to load through
<%= Rails.env.development? ? wicked_pdf_image_tag("img/logo.png") : wicked_pdf_image_tag("#{Rails.root}/public/assets/img/logo.png") %>
<%= Rails.env.development? ? wicked_pdf_image_tag("img/logo.png") : wicked_pdf_image_tag("#{Rails.root}/assets/img/logo.png") %>
<%= image_tag(ActionController::Base.helpers.asset_path('img/logo.png')) %>
How can I load s3 image in pdf file?
You can put the image in a s3 bucket and make it public. After that try it like below. If you use the below code no need to use separate syntax for different environments, it will works for all .Hope it works.
<%= wicked_pdf_image_tag('//s3.amazonaws.com/bucket_name/image.png') %>
I have worked on the similar functionality but using PDFKit gem. But I think rendering logic will be almost similar.
Below is the code where I rendered my partial in controller
def print_batch
batch = Batch.find(params[:id])
respond_to do |format|
format.pdf {
html = render_to_string("_batch",:formats => [:html], layout: false , locals: { batch: batch })
Rails.logger.debug(html.inspect)
kit = PDFKit.new(html)
send_data(kit.to_pdf, :filename => "file_name_#{batch.id}.pdf", :type => 'application/pdf') and return
}
format.html
format.json { render json: {id: batch.id, processed: batch.processed?} }
end
end
In _batch.html.haml. You can see I have used person.s3_logo for rendering the pdf image.
- logo_image_pdf = person.logo.present? ? person.s3_logo : default_credit_logo
- logo_image_html = person.logo.present? ? image_path(Person.logo.thumb('100x100').url) : image_path('default_credit_logo.png')
- logo_image = params[:format] == 'pdf' ? logo_image_pdf : logo_image_html
.bucks
%img.logo{src: logo_image }
In Person.rb model. Anyway we cannot directly render image in PDF file directly from s3. So any gem will first download it in /tmp folder and render it. This is how I have done it in my model file.
def s3_logo
file = open(self.logo.remote_url)
file.path if file
end

How to create pdf file with layout applied to it. Using pdfkit gem

require 'pdfkit'
html = render_to_string(:layout => 'layouts/test_layout' , :action => print_form.html.erb")
kit = PDFKit.new(html)
send_data(kit.to_pdf, :filename => "Form.pdf", :type => 'application/pdf')
above code generates PDF file without layout specified. How do I create PDF file with layout applied.
layouts/test_layout -> test.css, test.js
My test_layout contains some JavaScript and CSS files.
Please suggest me, I want to print form in PDF format with specified layout.
Without seeing your render_to_string method we can't tell what's going wrong. Here is example code for generating a pdf with layout: https://github.com/pdfkit/pdfkit#usage

wicked_pdf is not rendering header

render :pdf => "file_name",
:layout => 'pdf.html.erb',
:template => 'transactions/show.pdf.erb',
:wkhtmltopdf => WICKED_PDF_BIN,
:show_as_html => true,
:layout => 'pdf.html.erb',
:header => {:html => { :template => 'shared/header.pdf.erb'}}
PDF is generated fine, unfortunately I do not see the header. I can stick the header in the main layout and it works fine too. It seems to me that the header line above is not being processed. The filename 'header.pdf.erb' does not seem to matter. I can point it to a file that does not exist and it throws no error.
This is Mac OS, Rails 3.2.1, ruby 1.9
You may want to simply render the template as a string and assign it to the header's content. Try this out:
header: {
content: render_to_string(template: 'header.pdf.haml')
}
It works well for me.

Is there a way for acts_as_flying_saucer to save a file without calling render_pdf?

As the title says I use the Rails gem that works good but I want to separately save pdf's to a folder. Is there a way to do this without calling render_pdf?
This is what does not work:
render_pdf :template => 'caseprinttemplates/create_pdf_to_print.erb', :pdf_file => "/home/mattias/www/Inkasso/public/uploadedfiles/" + results[:title]
redirect_to new_interventionreminder_path(:case_id => #interventionreminder.case_id, :saved => "1")
return
This does work on another page:
render_pdf :template => 'caseprinttemplates/create_pdf_to_print.erb', :layout => nil, :send_file => { :filename => "samladutskrift.pdf"}
The acts_as_flying_saucer plugin is just a wrapper around the Flying Saucer java library. In the source, you can see that only a single wrapper method is defined: render_pdf().
https://github.com/dagi3d/acts_as_flying_saucer/blob/master/lib/acts_as_flying_saucer_controller.rb
You can, however, use render_pdf() to render to a file, like the examples found here:
# Renders the template located at '/foo/bar/pdf.html.erb' and stores the pdf
# in the temp path with a filename based on its md5 digest
render_pdf :file => '/foo/bar/pdf.html.erb'
# renders the template located at 'app/views/foo.html.erb' and saves the pdf
# in '/www/docs/foo.pdf'
render_pdf :template => 'foo', :pdf_file => '/www/docs/foo.pdf'
# renders the 'app/views/foo.html.erb' template, saves the pdf in the temp path
# and sends it to the browser with the name 'bar.pdf'
render_pdf :template => 'foo', :send_file => { :filename => 'bar.pdf' }

Resources