Rendering CSS using PDFKit - pdf

I know that there have been other questions about this, but I've read through them all and haven't figured this out yet. I'm using the PDFKit gem to allow users to generate .pdfs of content on my site. I can render a pdf by adding .pdf to the url, but CSS doesn't transfer along with it. I understand from Googling that it's because of the asset pipeline, but I haven't figured out how to make it work.
I've installed both of teh necessary gems:
gem 'pdfkit', '~> 0.6.2'
gem 'wkhtmltopdf-binary'
In my application.rb file I added 'require pdfkit' at the top and the following to the application class:
config.middleware.use PDFKit::Middleware
config.cache_classes = true
config.eager_load = true
I then ran rake middleware
I also added an initializer called pdfkit.rb with teh following code that I found, in order to fix the .pdf from endlessly loading:
ActionController::Base.asset_host = Proc.new { |source, request|
if request.env["REQUEST_PATH"].include? ".pdf"
"file://#{Rails.root.join('public')}"
else
"#{request.protocol}#{request.host_with_port}"
end
}
At this point adding .pdf to a url creates the pdf, but doesn't render the CSS at all. The README on pdfkit's github says:
"Resources aren't included in the PDF: Images, CSS, or JavaScript does not seem to be downloading correctly in the PDF. This is due to the fact that wkhtmltopdf does not know where to find those files. Make sure you are using absolute paths (start with forward slash) to your resources."
My CSS is called in the head as usual:
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
How do I make an absolute path? I don't think I just replace the stylesheet_tag with an ordinary
<link rel='stylesheet' href='bootstrap_and_customization.css.scss' type="text/css">

Related

How to set sinatra-authentication to use erb instead of haml?

I'm trying to set up the sinatra-authentication gem in a simple sinatra app, and running into an issue where sinatra can't find the correct views. I understand that sinatra-authentication uses haml by default, but I'm using erb in this app.
This in mind, I found in the sinatra-authenticaiton docs that there is a setting which allows you to change the template engine, by adding the following to your app file:
configure do
set :template_engine, :erb # for example
end
I've added this to my app.rb file, and sinatra is still looking for the signup.haml when I try to hit the /signup route in my app.
A couple of notes:
I've included the gem in my Gemfile, and successfuly run a bundle install on my app.
source 'https://rubygems.org'
gem 'sinatra'
gem 'data_mapper'
gem 'pg'
gem 'dm-postgres-adapter'
gem 'sinatra-authentication'
I saw something in the documentation that suggested that I may need to specify the location of my view files, so I added the following to my configuration block.
set :sinatra_authentication_view_path, Pathname(__FILE__).dirname.expand_path + "views/"
**I think I've required the gem accurately in my app file by adding
require "sinatra-authentication"
use Rack::Session::Cookie, :secret => 'mys3cr3tk3y'
This gist is a current representation of my app.rb file in the root of my sinatra app. https://gist.github.com/rriggin/5378641#file-gistfile1-txt
Here is a screenshot of the error sinatra throws: http://cl.ly/image/0y041t0K3u3O
When I run the app locally, a 'dm-users' table is created in my local db as expected.
Is there another configuration setting that I'm missing in order to get sinatra-authentication to properly look for the erb templates rather than haml files. Any help would be greatly appreciated.
Thanks
The specs don't test that the template_engine setting works, and looking at the way the setting is called, I believe it's not correct, i.e.
send settings.template_engine, get_view_as_string("index.#{settings.template_engine}"), :layout => use_layout?
might better work as:
send app.settings.template_engine, get_view_as_string("index.#{app.settings.template_engine}"), :layout => use_layout?
that's what I reckon. If you fork the project, change the line and add it to your Gemfile and it works then consider writing a quick spec for it and you'll have improved the mainline of that project as well as fixed your problem.

Rails asset pipeline - image_path helper only working in development

I have a problem with asset preocompilation in Rails (3.2.7).
I am including an favicon like this:
<link rel="icon" type="image/png" href="<%= image_path("favicon.png") %>" />
On development mode I set config.assets.compile = true. There everything works fine, the rendered HTML looks like this:
<link rel="icon" type="image/png" href="/assets/favicon.png" />
But on production, where I set config.assets.compile = false, I get the error
Sprockets::Helpers::RailsHelper::AssetPaths::AssetNotPrecompiledError in Home#index
...
favicon.png isn't precompiled
I already ran rake assets:precompile and i can clearly see, that the asset is available under public/assets/favicon.png.
I know, that i could set config.assets.compile = true in production, but i don´t want to do that (because of performance reasons).
Has anyone an idea, why my rails app is not able to resolve the correct path to the asset in production? Thanks!
Update:
maybe also useful to know: It happens not only for images, also for other assets.
For example <%= stylesheet_link_tag "screen", :media => "all" %> also produces the error screen.css isn't precompiled when config.assets.compile is set to false.
You must tell Rails which assets are to be precompiled. You do this in config/application.rb or config/environments/production.rb with the config.assets.precompile config key.
Rails starts with a default list of assets to precompile, including ["application.js", "application.css"], but if you want your own assets to be precompiled too, you have to add them to the list.
For example:
# config/application.rb
module MyApp
class Application < Rails::Application
# other config ...
config.assets.precompile += ["screen.css", "*.png"]
end
end
Ok, after a couple of tries I figured out, how to fix this. Nevertheless it´s a little bit strange and does not satisfy me completely. It only worked for me, when I set digest to true and provide the path to the manifest:
config.assets.compile = false
config.assets.digest = true
config.assets.manifest = Rails.root.join("public/assets")
It would be interesting to know, what´s behind this "logic".

pdfkit not rendering correctly in rails 3.1

I have followed the following railscast about adding pdfkit to an application, and I am having some issues with the generation of pdfs. Here are the following things that I have done:
I downloaded wkhtmltopdf via the homebrew package manager
brew install wkhtmltopdf
Then I added the pdfkit gem to my gemfile and ran the bundle install command. I added the following to my config/application.rb file
require 'pdfkit'
...
config.middleware.use PDFKit::Middleware, :print_media_type => true
I then changed my application layout file to include all stylesheet types.
If I run rake middleware, the command works and I can see the pdfkit middleware
When I try to append pdf to the end of my routes the application just hangs and I have to exit via the command line. If I create a link to the page I want to make into a pdf, it changes all of the markup so it looks like a corrupted file. (it looks like you opened a text file into a word processor or vice versa I can provide images if that helps) If I try to make css changes in my stylesheet they do not go into effect when I view them with the link to pdf. I am assuming that this has something to do with the new asset pipeline in rails has anyone else experienced this issue?
So I was right in assuming that my error had something to do with the asset pipeline, after doing some research it looks like you need to create a new initializer and add the following code:
ActionController::Base.asset_host = Proc.new { |source, request|
if request.env["REQUEST_PATH"].include? ".pdf"
"file://#{Rails.root.join('public')}"
else
"#{request.protocol}#{request.host_with_port}"
end
}

rails assets path

I have in
<link href="/assets/application.css" media="screen" rel="stylesheet" type="text/css" />
<script src="/assets/application.js" type="text/javascript"></script>
but when I go to http://localhost:3000/assets/application.css
Routing Error
No route matches [GET] "/assets/application.css"
P.S. Rails 3.1.0.rc4, ruby 1.8.7
Seems Sprockets / Rails 3.1 were acting up for me w/ ruby 1.9.2-p180 ... updating to Ruby-1.9.2-p290 seemed to stop the issue.
Maybe not related to your issue... but useful for anyone else having that issue using those versions of Rails & Ruby.
I found that I had something similar going on after updating to Rails 3.1 this evening. I was working on a project that didn't use ActiveRecord, so I had a modified my application.rb to exclude it. The line that usually reads require 'rails/all' to only include the parts I needed, like this:
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "rails/test_unit/railtie"
This list has changed in Rails 3.1 to include Sprockets, the core component to making the asset pipeline work. I got the asset pipeline serving the serving content as expected by adding this line to the bottom of the list:
require "sprockets/railtie"
After restarting, /assets/application.js and other assets began working as expected.
Note: if you have a custom setup like this, be sure to open the railties gem and look at the contents of lib/rails/all.rb which may have changed (as in this case).
Your scripts and styles will be loaded from the public folder. Drop the assets folder under public and you should be good to go.
In the application layout file, if you have
<%= stylesheet_link_tag "/assets/application" %>
which gives
No route matches [GET] "/assets/application.css"
TRY changing it to
<%= stylesheet_link_tag "application" %>
I had to add the following line in application.rb:
config.assets.enabled = true
in bottom of class Application < Rails::Application

Princely is generation text/html instead application/pdf?

I'm using Princely and Rails 3.
When I try to render a pdf like this..
respond_to do |format|
format.pdf do
render :pdf => "filename", :template => "path/template.pdf"
end
end
The downloaded file is a text/html format.
How can I fix this and make it work. I have already added the line bellow to config/initializers/mime_types.rb
Mime::Type.register "application/pdf", :pdf
I had the same problem yesterday and came across this question in my search for a solution.
In my case, I had the Princely gem installed globally (well, in my global RVM repo) rather than anywhere in my project's directory structure. So none of the Princely code was ever being loaded. I ended up making a new "prince.rb" file in my project's conf/initializers with the following:
require 'princely'
require 'princely/rails'
At that point I still got rails errors because Princely 1.2.5/lib/princely/pdf_helper#stylesheet_file_path refers to ActionView::Helpers::AssetTageHelper, which is apparently a Rails 2ism. I just changed that method's body to "return stylesheet" and then everything worked.
I'm still fairly new to Rails; maybe someone that knows more can chime in with a better way.