Rails assets compile application.js file on Heroku - ruby-on-rails

I have couple of vendor js files and I put them in the application.html.erb of bottom of body tag as;
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta charset="utf-8" />
<title><%= full_title(yield(:title)) %></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta content="" name="description" />
<meta content="" name="author" />
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" />
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<% if (controller.controller_name == "main") %>
<body class="fixed-header no-header">
...
<%= javascript_include_tag 'pace/pace.min', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'modernizr.custom', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'jquery-ui/jquery-ui.min', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'boostrapv3/js/bootstrap.min', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'jquery/jquery-easy', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'jquery-unveil/jquery.unveil.min', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'jquery-bez/jquery.bez.min', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'jquery-ios-list/jquery.ioslist.min', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'jquery-actual/jquery.actual.min', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'jquery-scrollbar/jquery.scrollbar.min', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'bootstrap-select2/select2.min', 'data-turbolinks-track' => true %>
...
</body>
</html>
Then I declared them for Rails to be able compile (config/initializers/assets.rb)
Rails.application.config.assets.precompile += %w( pace/pace.min.js modernizr.custom.js jquery-ui/jquery-ui.min.js boostrapv3/js/bootstrap.min.js jquery/jquery-easy.js jquery-unveil/jquery.unveil.min.js jquery-bez/jquery.bez.min.js jquery-ios-list/jquery.ioslist.min.js jquery-actual/jquery.actual.min.js jquery-scrollbar/jquery.scrollbar.min.js bootstrap-select2/select2.min.js switchery/js/switchery.min.js ...)
Then I have signup to heroku and created an app then I typed;
1. bundle exec rake assets:precompile RAILS_ENV=production
2. git add .
3. git commit -m "smth"
4. git push heroku master
app works fine but the problem is in the network tab. I have application.js file but I have all the vendor js files individually. Should not be rails compiling them to 1 file ?
EDIT:
I really could not figure it out how should I include vendor js files to rails app. As most of the js files work after the dom loads, I would like them to load at the end of body tag.
I removed the app and push again to heroku. I changed nothing. Now the js files works but weirdly it seems not loading.
I did not require any vendor file in application.js file.
EDIT 2
I really appreciate your answer and trying to understand one more thing.
Lets say I have a model called main.rb so I have main folder and home.html.erb file. Rails creates main.coffee ( I changed it to main.js.coffeee). So if I put all the relevant js codes into this file (main.js.coffee), whenever home.html.erb is called this js code will automatically called after page loads, is that how it works?. If so, I will organize page specific js codes like this. thank you

You are loading them all directly from the page as well as from the concatenated precompiled file so what you are seeing is the concatenated file being loaded and then the libraries are getting reloaded a second time from the separate js include tags in your application.html.erb file! What you need to do is require them in your app/assets/javascripts/application.js file so that they are loaded once.
For example in your app/assets/js/application.js file should be:
//= require pace/pace.min
//= require bootstrap-select2/select2.min
Do this for all the js files and then make sure if any js files aren't working properly to account for turbolinks by calling the page:change event as described here:
Rails 4: how to use $(document).ready() with turbo-links
EDIT: Loading js libraries in the Head tag is noramlly fine because they're all usually wrapped in a $(document).ready call so there is no need to force them into the end of the page like you would for php and other platforms. The Rails Way to handle this is to require them as stated in your application.js and then run bundle exec rake assets:precompile RAILS_ENV=production . Then do another git add and commit and then push to heroku!
Now, to do what you want and keep js at the bottom of specific pages you have to realize your application.html.erb gets called for every page request so you're essentially loading this script into every page like your application.js asset file is designed for. If you want to only call js on specific pages and at the bottom you can do the following:
In your application.html.erb file at the very bottom before the closing body tag you can put:
<%= yield :javascript %>
Then on all view pages where you have some script or library you'd like to include you can put at the very bottom of that view:
<%= content_for :javascript do %>
<script src="jquery-1.12.2.min.js"></script>
<script type='text/javascript'>
all your custom js here....
</script>
<% end %>
This will yield the block of js to the :javascript in your application.html.erb at the bottom as desired.
Edit 3:
You'll notice the standard Rails application.js file has a "require_tree" directive. This basically loads all js so scripts that you have in your main.js folder will fire on anything referencing them in any other part of your application. To avoid this you can do what I do and remove these directives and call things individually. This is a bit more advanced but I'll walk you through it since it's hard to put it all together on docs scattered around the internet. This is how to load page specific assets and the ideal way to handle assets in Rails.
In your application.js file remove the require_tree and only //=require files you want application wide whether it's libraries in your vendor js folder or personal scripts. Once that is done, you'll need to change your application.html.erb file as follows:
In the head tag you can keep the "javascript_include_tag application" call since that will do what you want and pull all app. wide js files. Then at the bottom of this file above the closing body tag put:
<%= javascript_include_tag params[:controller] if ::Rails.application.assets.find_asset("#{params[:controller]}.js") %>
This will then call only the js file with the matching controller name such as 'main.js' in your example. I also then under this line use a yield to javascript code that may be on other views:
<%= yield :javascript %>
Then on pages with page specific js I put it at the very bottom of its respective view and don't add it to my assets/js folder at all:
<%= content_for :javascript do %>
<script type='text/javascript'>
code here
</script>
<% end %>
Now you're almost done. Because you will be loading files by controller you need to add them to your Rails precompile list! So for example, your 'main.js' file, even if it is autocreated when generating a controller, must be added to this precompiled array with all other controller js files. To do this open up your config/initializers/assets.rb file and uncomment the following line and add all js files named after controllers:
Rails.application.config.assets.precompile += %w ( main.js )
Now restart your server and you are done! I do this for css files as well!
Note: If you have js libraries that are only used in one page you can do the //= require statement in those controller related js files. //= require is not limited to the application.js file!

Related

Dynamically loaded assets in Rails 4 and Turbolinks

I am working on a Rails 4 app in application.html.erb I have the following code
....
<head>
<title>...</title>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= yield :head %>
<%= csrf_meta_tags %>
</head>
What this does is allows me to load certain assets depending on the page I am on. So maybe in the show template of a certain action I could do something like
<% content_for :head do %>
<%= stylesheet_link_tag "show" %>
<% end %>
This works great and helps me keep the page structured clean and simple. The issue I am having now is that turbolinks is completely ignoring these assets and not even loading them when I click on a next link. I have looked around but cant seem to find an answer to this problem. Any help will be appreciated.
I had the same problem, try to add data-turbolinks-track into your stylesheet tag
This is most likely because turbolinks does not replace the <head> element:
Turbolinks makes following links in your web application faster. Instead of letting the browser recompile the JavaScript and CSS between each page change, it keeps the current page instance alive and replaces only the body and the title in the head. Think CGI vs persistent process.
As such, any changes to the <head> element will be ignored.

JavaScript is secretly running on my Rails application

My only line in the routes file is this:
root :to => 'spikes#index'
In the Javascript assets I have a simple function like this:
spike.js file:
$(function(){
alert("WAT");
document.write("abc");
});
In the Views->spikes->index.html.haml file I have NOTHING! it is empty.
I used to have the following code, but I removed it:
= javascript_include_tag 'spike'
But still when I run my Rails app, I see an alert and "abc" written on the browser.
Where is it calling it from? What on earth!?!
UPDATE: This is also my application.html.erb file:
<!DOCTYPE html>
<html>
<head>
<title>D3Spike</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
You probably have a <script> tag in app/views/layouts/application.html.erb (or maybe .haml, not .erb), which wraps all your pages. If you take that out for a second, you'll probably see the alert go away.
A couple things to understand: 1) the JavaScript code you showed us runs just by virtue of being included (paste it into a console in your browser to see what I mean) and 2) in Rails, the normal behavior is for all your JavaScript to be included all the time, which is perhaps not what you expected.

Configuring Rails Asset Pipeline in dev and production

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.

I didn't set path for css, but the css effect is working , why?

There is nothing in application.css.
I have put a file named "cake.generic.css" in app/assets folder. If i load the home page the cake.generic.css is loading and working staraightway. Why is it working. I didn't set this path in application.html.erb.
<head>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
In Rails 3.1, there is an asset pipeline (check Rails guides).
Basically, in your application.css, all css files are required by default. It lets you have a nice unique and compressed file in production
check this:
http://railscasts.com/episodes/279-understanding-the-asset-pipeline
http://railscasts.com/episodes/282-upgrading-to-rails-3-1

Rails custom css links are not working - following tutorial in http://ruby.railstutorial.org

I'm new to rails and working my way into the tutorial here: http://ruby.railstutorial.org/ruby-on-rails-tutorial-book
I've added the blueprint css package to the public/stylesheets directory and added a custom.css file however I cannot seem to get the stylesheet to load. From my understanding fo the setup the page should have a blue background and some other small changes.
In my app/views/layouts/application.html.erb file I've added the following line:
<%= stylesheet_link_tag 'stylesheets/custom', :media => 'screen' %>
Which I believe should cause the css from the /public/custom.css to load.
In the tutorial the content of the custom.css file is located in section 5.1.2 (sorry I'm only able to post 2 hyperlinks here)
.
And the content of the app/views/layouts/application.html.erb file is here:
http://ruby.railstutorial.org/chapters/filling-in-the-layout#sec:adding_to_the_layout
When I view source on the page there is a link to the custom.css file here:
But clicking that brings up a "Routing Error - No route matches "/stylesheets/stylesheets/custom.css"" message.
As far as I can find I've followed the tutorial exactly so I'm not sure what is wrong or what I've missed. Any help on where to go from here would be appreciated.
complete text of the application.html.erb file:
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<%= csrf_meta_tag %>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<%= stylesheet_link_tag 'blueprint/screen', :media => 'screen' %>
<%= stylesheet_link_tag 'blueprint/print', :media => 'print' %>
<!--[if lt IE 8]><%= stylesheet_link_tag 'blueprint/ie' %><![endif]-->
<%= stylesheet_link_tag 'custom', :media => 'screen' %>
</head>
<body>
<div class="container">
<header>
<%= image_tag("logo.png", :alt => "Sample App", :class => "round") %>
<nav class="round">
<ul>
<li><%= link_to "Home", '#' %></li>
<li><%= link_to "Help", '#' %></li>
<li><%= link_to "Sign in", '#' %></li>
</ul>
</nav>
</header>
<section class="round">
<%= yield %>
</section>
</div>
</body>
</html>
This still has the same error when clicking the custom.css link in source as before:
"Routing Error - No route matches "/stylesheets/stylesheets/custom.css""
is this happening on localhost or production environment? If it's production then open config/production.rb and change:
config.serve_static_assets = false
to
config.serve_static_assets = true
If this is happening in development environment then I'm wondering if you possibly have more than 1 layout file. Check to make sure you don't have application.html.erb and application.html.haml. It's also possible that you have a separate layout for your posts, which would be titled post.html.haml or something...
ALSO
you state the following:
Which I believe should cause the css from the /public/custom.css to load.
If your custom.css file is located in public/custom.css then it is in the wrong place, it should be in public/stylesheets/custom.css
EDIT:
below is a screenshot of your app as it appears on my machine, it looks like it works ok after moving stylesheet into the right folder. I also took the liberty of deleting public/index.html, but you can leave it in for now until the tutorial advises you to take it out
Change it to stylesheet_link_tag 'custom', :media => 'screen'. It will automatically look in the /public/stylesheets/
So I'm not sure if you ever figured this out (I'm sure you did), but I just had the same issue, and found a solution. It looks like rails is looking in /app/assets/stylesheets instead of /public/stylesheets. I'm not sure if this is the correct way it should be working, but I moved my custom.css file there and everything is now working fine.
I had a similar problem following the tutorial but it hit me in chapter 4 where we first include the helper for the blueprint css files. I am using Rails v. 3.1.3, and for me nnaficy's answer solved the problem. Heres the description of why this is happening from the rubyonrails guide :
(source: http://guides.rubyonrails.org/layouts_and_rendering.html)
"3.1.2 Linking to JavaScript Files with the javascript_include_tag
The javascript_include_tag helper returns an HTML script tag for each source provided.
If you are using Rails with the Asset Pipeline enabled, this helper will generate a link to /assets/javascripts/ rather than public/javascripts which was used in earlier versions of Rails. This link is then served by the Sprockets gem, which was introduced in Rails 3.1."
(i copied the above for the explanation, but specific to css is the following snippet:)
"3.1.3 Linking to CSS Files with the stylesheet_link_tag
The stylesheet_link_tag helper returns an HTML tag for each source provided.
If you are using Rails with the “Asset Pipeline” enabled, this helper will generate a link to /assets/stylesheets/. This link is then processed by the Sprockets gem. A stylesheet file can be stored in one of three locations: app/assets, lib/assets or vendor/assets."
so instead of copying my blueprint folder to public/stylesheets/, i copied it to app/assets/stylesheets/ and the css did its magic.
Change the line:
<%= stylesheet_link_tag '/stylesheets/application', :media => 'screen' %>
to
<%= stylesheet_link_tag '/stylesheets/custom', :media => 'screen' %>
It worked for me.
Also, for those who are still working on the problem, check that you are puting the CSS in the right project. I had a folder called "sample_app" in which I started the tutorial. Some days after, I started using Aptana/RadRails, which created a custom project folder (workspace). I didn't realized and put all my css in my initial "sample_app" folder. That's why Rails could not find the css/logo!
Same question with my current Rails 3.2.6 app. I've solved it with this include function:
<%= stylesheet_link_tag '/stylesheets/custom', :media => 'screen' %>
You have to use absolute path's instead of relative ones.
Ok so maybe someone out there is still struggling, I've been trying to figure these out for a while now and i have solved the problem. Like #shime is saying Rails looks in public/stylesheets.
application.html.erb
-----------------
`<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<%= csrf_meta_tag %>
<%= stylesheet_link_tag **'screen'**, :media => 'screen' %>
<%= stylesheet_link_tag **'print'**, :media => 'print' %>
</head>
<body>
<%= yield %>
</body>
</html>`
Move screen.css and print.css from stylesheet/blueprint to app/assets/stylesheets.

Resources