Princely hanging with 'undefined method `force_encoding' for nil:NilClass'
schwarzh opened this issue · 17 comments
This might be a bit of a newbie question, and I hope I'm asking it in the right place.
Using Ubuntu 10.10, ruby 2.0.0p247, Rails 4.0.0, latest princely, Prince 9.0 rev 2
When I try to create a pdf using the below:
respond_to do |format|
format.pdf do
render :pdf => "preview",
:template => "projects/preview.pdf.erb",
:layout => "preview"
end
end
Or by using 'make_and_send_pdf("preview")', the server hangs with this line:
PRINCE XML PDF COMMAND
/usr/bin/prince --input=html --server --log=/home/schwarzh/rails/generator/log/prince.log --silent - -o -
When I ctrl-c the rails server, I get an error of:
Completed 500 Internal Server Error in 88847ms
NoMethodError (undefined method force_encoding' for nil:NilClass): app/controllers/projects_controller.rb:111:in
preview'
Line 111 is 'render :pdf => "preview",'
I'm able to create a pdf using prince on the command line from the same HTML that I'm rendering in Rails. Am I doing something wrong or have I encountered a bug?
Thanks,
Brad
I have a feeling that it might be PrinceXML itself that is taking a long time here. When you ctrl+c, you kill the PrinceXML instance, returning nil to Princely which can't cope with that response. How big is the template you're rendering, or how much data are you rendering into it?
The template that I'm rendering is very small - just a few words in HTML. If I access the HTML version of the page (which is the exact same HTML as the pdf version), then save it as HTML and run Prince from the command line it outputs the pdf in a second or 2 tops.
If you run it, do a ps aux | grep prince
or check Activity Monitor (etc), do you see the prince process working? high cpu usage, etc
It appears to be running when I access the Rails page to generate the pdf, but doesn't appear to be using much CPU:
schwarzh 3549 0.1 1.5 46692 24592 pts/1 S+ 07:09 0:00 /usr/lib/prince/bin/prince --input=html --server --log=/home/schwarzh/rails/generator/log/prince.log --silent - -o -
Can you try running the command on your saved html file and see if that has similar behaviour? /usr/lib/prince/bin/prince --input=html --server --log=/home/schwarzh/rails/generator/log/prince.log --silent <your test file> -o <output file>
Good question. I ran this and it came back almost instantly with success:
➜ generator git:(master) ✗ /usr/lib/prince/bin/prince --input=html --server --log=/home/schwarzh/rails/generator/log/prince.log --silent preview_test.html -o preview_test2.pdf
zsh: correct 'preview_test2.pdf' to 'preview_test.pdf' [nyae]? n
fin|success
It could be something in rails or something to do with socket pipes. Can you try generating it manually from a file in a console?
Princely.pdf_from_string(File.read(<your file name>))
Hmm... it's not seeing pdf_from_string?
2.0.0p247 :008 > Princely.pdf_from_string(File.read("preview_test.html"))
NoMethodError: undefined method pdf_from_string' for Princely:Module from (irb):8 from /home/schwarzh/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/commands/console.rb:90:in
start'
from /home/schwarzh/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/commands/console.rb:9:in start' from /home/schwarzh/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/commands.rb:64:in
<top (required)>'
from bin/rails:4:in require' from bin/rails:4:in
Sorry, writing from my phone. Should be: Princely.new.pdf_from_string(File.read("preview_test.html"))
Hmm...
Princely.new gives this error:
2.0.0p247 :002 > Princely.new
NoMethodError: undefined method new' for Princely:Module from (irb):2 from /home/schwarzh/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/commands/console.rb:90:in
start'
from /home/schwarzh/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/commands/console.rb:9:in start' from /home/schwarzh/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.0/lib/rails/commands.rb:64:in
<top (required)>'
from bin/rails:4:in require' from bin/rails:4:in
Maybe Princely is not installed properly? I have this in my GemFile:
gem 'princely', :git => 'git://github.com/mbleigh/princely.git'
And I have a princely.rb initializer in /config/initializers/ that contains:
require 'princely'
require 'princely/rails'
I've tried removing this initializer and get the same result.
Give it a shot using the latest released version of the gem (1.4.1) rather than the git version, which is operating on prerelease 2.0.0. gem 'princely', '1.4.1'
Ok, the command now works in the console - it outputs a large string of data to the console, but does not create a pdf even if I pass a pdf name to it. It still hangs when running through rails server (ie. accessing the page in Chrome).
2.0.0p247 :005 > p = Princely.new
=> #<Princely:0xbc511b4 @exe_path="/usr/bin/prince", @style_sheets="", @cmd_args="", @log_file=nil, @logger=nil>
2.0.0p247 :006 > p.pdf_from_string(File.read("preview_test.html"), "preview_test4.pdf")
PRINCE XML PDF COMMAND
/usr/bin/prince --input=html --server --log=/home/schwarzh/rails/generator/log/prince.log --silent - -o -
fin|success
=> "%PDF-1.4\n%\xE2\xE3\xCF\xD3\n\n1 0 obj\n<</Type /Catalog\n/Pages 2 0 R>>\nendobj\n\n2 0 obj\n<</Type /Pages\n/Kids [3 0 R]\n/Count 1>>\nendobj\n\n7 0 obj\n<</Length 8 0 R\n/Filter /FlateDecode>>\nstream\nx\x9C\x8DR\xB9n\x83@\x10\xED\xE7+\xB6tR\xAC\xF7\xDE%e.+M\xAC\xC8H)\xAC\x146\xAC\x8F\bp\xCC!\x94\xBF\xCFb\xC0\x1C\xA6\b\x143\xBC}3\xEF\xCD\xB0g \x98\xB8\a5AQV'\xDAk\x92\xD4\xC2\xE7=$p\x86\xEB\xD......................
The large string is the PDF data, this command only generates a string. You can generate to file by doing p.pdf_from_string_to_file(File.read("preview_test.html"), "preview_test4.pdf")
Just checking, you've restarted the rails server after changing the gem file?
pdf_from_string_to_file generated a file.
I did restart the rails server.
I think I just found the problem - the pdf version of the template wasn't finding an image file and that was causing it to hang. I was looking for the image file by referencing the full url:
background: url('http://0.0.0.0:3000/assets/header.png') no-repeat top left;
And that made it hang. The odd thing about this is that header.png comes right up in a browser if you paste that string into the server. I'm actually having trouble getting the file to come into the pdf at all, although I can get other image files on the web to show up in the pdf when I used their url. The image is in /public/assets/, so using
background: url('/assets/header.png') no-repeat top left; should find it right? BTW - using this image location does not cause it to hang - only when it tried to access the image using 'http://0.0.0.0:3000/assets/header.png'. Using a non existent public url doesn't make it hang either.
Thanks much for your help in finding this issue.
Update: using "background: url('public/assets/header.png') no-repeat top left;" found the file and properly brought it into the pdf.
Brad
Ah yes. Prince runs seperate to the web server and so it needs a file path. We've got some stuff that rewrites paths so that it's compatible with prince; perhaps that needs a shortcut into /public/assets.
It's concerning though that the service hung instead on a not-found file. I wonder if there's anything that can be done about that.