When I recently started on a mobile version of my app I realized that I had no use of all javascript code written for desktop clients. So I put this in application.html.erb
<% if mobile_agent? %>
<%= javascript_include_tag "mobile" %>
<%= stylesheet_link_tag "mobile", :media => "all" %>
<% else %>
<%= javascript_include_tag "desktop" %>
<%= stylesheet_link_tag "desktop", :media => "all" %>
<% end %>
And in app > assets > javascripts I created this structure
- desktop.js
- mobile.js
- desktop/file1.js
- desktop/file2.js
- mobile/file1.js
- mobile/file2.js
- shared/file1.js
- shared/file2.js
And in mobile.js:
//= require_tree ./mobile
//= require_tree ./shared
And in desktop.js
//= require_tree ./desktop
//= require_tree ./shared
In development env that has worked fine, but when I have deployed to Heroku it gives me an error:
Completed 500 Internal Server Error in 100ms
ActionView::Template::Error (mobile.js isn't precompiled):
8: <meta name="format-detection" content="telephone=no">
11: <%= javascript_include_tag "mobile" %>
9:
12: <%= stylesheet_link_tag "mobile", :media => "all" %>
10: <% if mobile_agent? %>
Parameters: {"community_category"=>"swingdancing", "city"=>"stockholm"}
app/views/layouts/application.html.erb:11:in 78182492067426179_45617280'
13: <% else %>
Completed 500 Internal Server Error in 2ms
app/controllers/communities_controller.rb:20:in `show'
Processing by ErrorsController#show as HTML
14: <%= javascript_include_tag "desktop" %>
/app/vendor/bundle/ruby/1.9.1/gems/actionpack-3.2.13/lib/sprockets/helpers/rails_helper.rb:142:in Error during failsafe response: mobile.js isn't precompiled
What is causing this error and how can I resolve it?
what to do ?
simply add
config.assets.precompile += %w(mobile.js)
to config/application.rb
why ?
when you deploy to production environment, by default rails uses the asset pipeline.
This means that instead of serving directly the files that are in assets/, rails assumes that you have run rake assets:precompile beforehand, and that there are concatenated, compressed and minified versions of your assets in an another folder.
This implies that each and every asset you intend to load from the browser should be precompiled. The benefit is that instead of serving many human-readable files, you only serve a few that have been minified - less connections, less volume = faster load time.
This feature is inactive in development mode because you would have to recompile the assets at each request, and moreover being able to read js and css is quite usefull for debugging.
Related
I've got a new spree rails 6 application and I can't get any of the sass files to compile. Here's my assets/stylesheets file:
stylesheets
app
_file.scss
_another_file.scss
mixins
_mix-media-queries.scss
_mix-general.scss
modules
_modules_file.scss
application.css
style.scss
application.css:
*= require_tree .
*= require_self
*= require ./style
style.scss:
#import "mixins/_mix-media-queries";
etc...
But when I load the page it give me this error:
Error: Undefined variable: "$color-dark-red". Which is an var in the mixins file.
_head.html.erb:
<title><%= title %></title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<%== meta_image_data_tag %>
<%== meta_data_tags %>
<%= canonical_tag(current_store.url) %>
<%= favicon_link_tag 'favicon.ico' %>
<%= stylesheet_link_tag 'spree/frontend/all', media: 'screen', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_link_tag "application", media: "all" %>
<%= csrf_meta_tags %>
<%= render 'spree/shared/paths' %>
<%= javascript_include_tag 'spree/frontend/all', defer: true, 'data-turbolinks-track': 'reload' %>
<%= yield :head %>
This is so frustrating as I cannot get the stupid styles to load! I'm new to rails 6, is this a new rails 6 thing with the asset pipeline?
Sprockets directives do not work well at all with SASS.
When you require SASS files with sprockets it will send the files through the SASS compiler one by one and then concatenate the results together. Of course this blows up as soon as one of your SASS files references a variable, include or function that is declared in any other file.
You need to change the extension of your application.css to .scss and only use SASS #import directives that tells the SASS compiler to pull in the other file.
is this a new rails 6 thing with the asset pipeline?
No. This applies to previous versions of Rails and both SASSC and the old Ruby Sass Compiler.
See:
https://github.com/rails/sass-rails#important-note
I'm able to download pdf file with:
curl google.com | wkhtmltopdf - test.pdf
so it means, wkhtmlpdf installation was successful.
But, when I try to generate pdf file by accessing http://localhost:3000/contacts/1.pdf it hangs. In the status bar it shows: Waiting for localhost...
Rails server output:
Started GET "/contacts/1.pdf" for 127.0.0.1 at 2013-07-28 21:45:06 +0900
ActiveRecord::SchemaMigration Load (0.1ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by ContactsController#show as HTML
Parameters: {"id"=>"1"}
Contact Load (0.3ms) SELECT "contacts".* FROM "contacts" WHERE "contacts"."id" = ? LIMIT 1 [["id", "1"]]
Rendered contacts/show.html.erb within layouts/application (1.4ms)
Completed 200 OK in 99ms (Views: 57.0ms | ActiveRecord: 0.7ms)
Gemfile:
gem 'pdfkit'
application.rb:
config.middleware.use "PDFKit::Middleware"
According to the PDFKit railscast this should be enough for generating pdf files just by adding .pdf ...
UPDATE:
show.html.erb:
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #contact.name %>
</p>
<p>
<strong>Age:</strong>
<%= #contact.age %>
</p>
<%= link_to 'Edit', edit_contact_path(#contact) %> |
<%= link_to 'Back', contacts_path %>
layouts/application.html.erb:
<!DOCTYPE html>
<html>
<head>
<title>Pdftest</title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
UPDATE 2:
Thanks to #Arman H for helping me to figure out that I have to specify absolute path for assets instead of a relative ones. When I removed the following lines I was able to generate PDF file:
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
Now, I can't get how to substitute this with an absolute paths. It seems this post is what I need, but I still can't figure out how this would look like for my case.
The issue was due to stylesheet_link_tag and javascript_include_tag using relative URLs, which often causes wkhtmltopdf to hang when loading assets from the same server that wkhtmltopdf is running on.
Using absolute URLs for assets solved the problem.
Set asset_host in Rails' config, which also affects stylesheet_link_tag and javascript_include_tag:
# Modify asset host config setting in `config/application.rb`
# Or create a new initializer: `config/initializers/wkhtmltopdf.rb`
config.action_controller.asset_host = "http://mysite.com"
# Or you can have different hosts for development (local) and production (CDN):
# In `config/environments/development.rb`
config.action_controller.asset_host = "http://localhost"
# In `config/environments/production.rb`
config.action_controller.asset_host = "http://d111111abcdef8.cloudfront.net"
Setting config.action_controller.asset_host = "http://localhost"
in development.rb actually didn't work for me. That is, the PDF generation would work, but then assets wouldn't come through when rendering HTML.
I followed the method here: http://jguimont.com/post/2627758108/pdfkit-and-its-middleware-on-heroku
and it worked like a charm for me. Hope this helps someone. Just throw assets.rb in config/intializers and you're good to go.
I had the same issue in which my log showed the page had rendered however no pdf was generated and the browser would hang. It ended up having nothing to do with OS compatability, missing librariers, gems nor dependencies but instead I needed to raise the max allowable thread count for my Puma server (which had been set to 1) upto 2 or more. This then generated pdf's as normal.
I want to use //= require <lib> from a different file than /app/assets/javascripts/application.js. This results in a asset compile error but the problem is that the path is incorrect. I made a simplified project that show the problem available at https://github.com/rusanu/test-ember.
In the layout:
<head>
<title>TestEmber</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<%= yield :head %>
<%= csrf_meta_tags %>
</head>
In the view:
<%= content_for :head do %>
<%= javascript_include_tag "dashboard/dashboard", :cache => 'dashboard' %>
<% end %>
and in my dashboard/dashboard.js:
//= require handlebars
//= require ember
//= require ember-data
//= require_self
This results in error:
Showing /home/rremus/test-ember/app/views/dashboard/show.html.erb where line #2 raised:
No such file or directory - Asset file not found at '/home/rremus/test-ember/public/home/rremus/.rvm/gems/ruby-2.0.0-p0/gems/handlebars-source-1.0.0.rc4/dist/handlebars.js'
Extracted source (around line #2):
1: <%= content_for :head do %>
2: <%= javascript_include_tag "dashboard", :cache => 'dashboard' %>
3: <% end %>
4:
5: <h1>Dashboard#show</h1>
Notice how the asset path consist of the project public directory (/home/rremus/test-ember/public) and then correct asset path (/home/rremus/.rvm/...) is appended, resulting into an incorrect path.
My guess is that you have to do some special gymnastics to get it working with the cache directive in this case based on the Rails guide for the asset pipeline.
If you ditch the cache directive and rely on precompilation to handle file combination then things seem to work without error.
I have installed turbo-sprockets-rails3 gem for precompile assets with capistrano.
I have added load 'deploy/assets' to my Capfile and the deploy finish fine.
However when I try load my app on remote server I can see inside my production.log file the next errors:
ActionView::Template::Error (bootstrap-modalmanager.js isn't precompiled):
7: <%= display_meta_tags :site => "9cvs" %>
8: <%= stylesheet_link_tag "application", :media => "all" %>
9: <%= javascript_include_tag "application" %>
10: <%= javascript_include_tag "bootstrap-modalmanager" %>
11: <%= javascript_include_tag "jquery.back_to_top" %>
12: <%= javascript_include_tag "swfobject" %>
13: <%= csrf_meta_tags %>
bootstrap-modalmanager.js is found inside vendor/javascripts/ folder. Also I have css files inside vendor/stylesheets/ and swf files inside vendor/flash/ folder.
How can I precompile this assets correctly?
You need in your production.rb
config.assets.precompile += ['bootstrap-modalmanager.js', 'jquery.back_to_top.js', 'swfObject.js']
I am still not quite sure about the best practice of using rails asset pipeline. In a rails skeleton project, the application.html.erb contains code as:
<head>
<title>My title</title>
<%= stylesheet_link_tag "scaffolds" %>
<%= stylesheet_link_tag "depot", media: "all" %>
<%= stylesheet_link_tag "application", media: "all" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
Now in development, all js and css would be served properly. But in production, after precompile all the asset (js and css), I only need application.css and application.js, as scaffolds.css and depot.css are concatenate in application.css. So scaffolds.css and depot.css are no longer needed in production.
How could I have the above code in dev and then in production, have asset pipeline know certain assets have been concatenated in application.css/js and then remove those asset link tag in the code?
If this is not possible, how should I avoid loading redundant resources and keeping prod deployment manageable? (meaning no deleting the link_tag manually in production)
Thanks.
You do not put
<%= stylesheet_link_tag "scaffolds" %>
<%= stylesheet_link_tag "depot", media: "all" %>
<%= stylesheet_link_tag "application", media: "all" %>
in your layout file. You only put
<%= stylesheet_link_tag "application", media: "all" %>
And in config/environment/development.rb you make sure you have
config.assets.debug = true
When config.assets.debug is set to true it will automatically generate the <link ... /> tags for each of your stylesheets in dev mode for each assets required in the application.css file's Sprockets directives.
In config/environment/production.rb config.assets.debug will be false by default, causing the assets to be concatenated together into a single application.css file (again, assuming your //= require lines are correct in application.css). This will cause 1 link tag to be created for only application.css in production.