Ruby on Rails CSS/JS error with Turbolinks - ruby-on-rails

I'm building a web app on ROR5 and the layout/design is all done, with the CSS/JS files finalized. But when I open the app, click on one link, and navigate through the website, the CSS fails to load. More specifically, the CSS is all messed up. For example, say I go from 'Home' -> 'Page A', then if I backspace to 'Home' again (or click the logo to navigate to 'Home'), the 'Home' page will be messed up. Only when I refresh the page, I would get the correct display.
At first I thought it was a cache problem, but soon discovered that this line is causing the issue:
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
When I delete this line, the display issue is no longer present. However, all JS effects/JS-based plugins would not work. I have a text editor, a few jQuery animations and tab navigations, which all don't work when I delete that line.
+ of course, instead of just deleting the line, I also tried to simply disable turbolinks by doing:
<%= javascript_include_tag 'application' %>
and removing turbolinks from my Gemfile. This also didn't work.
My Gemfile includes:
gem 'turbolinks', '~> 5'
gem 'coffee-rails', '~> 4.2'
gem 'jquery-rails'
And the remaining GEMs are all standard gems for my frontend side (bootstrap, SASS, font awesome etc).
My application.js looks like this:
//= require rails-ujs
//= require jquery
//= require jquery_ujs
//= require tinymce
//= require turbolinks
//= require bootstrap-sprockets
//= require_tree .
And for reference, my application.html.erb contains a like the following:
<head>
<title>..</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= stylesheet_link_tag params[:controller] %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Adobe Typekit Scripts -->
<script src="https://use.typekit.net/ovy4zfg.js"></script>
<script>try{Typekit.load({ async: true });}catch(e){}</script>
</head>
What could be the problem? Thanks.

I think the issue here is that you're loading in controller-specific stylesheets (<%= stylesheet_link_tag params[:controller] %>). Turbolinks will append new stylesheets, but will not remove those that are absent in subsequent page loads. So here is the flow:
User visits Home
Stylesheet for Home's controller loaded
User visits Page A
Stylesheet for Page A's controller loaded after the Home CSS
Home CSS and Page A CSS will remain in the head
If possible, include all your CSS in the application.css manifest file. If you have some controller-specific styles, try adding a class to the body, e.g.:
<body class="<%= controller_name %>">
Then you can scope your styles, e.g. for a pages_controller:
body.pages {
…
}
Alternatively you could add data-turbolinks-track="reload" to your CSS link tag:
<%= stylesheet_link_tag params[:controller], 'data-turbolinks-track': 'reload' %>
However, this will mean that you will only get the benefits of Turbolinks when navigating between pages that use the same controller. When navigating between pages that use a different controller, you will get a full page load. This is because Turbolinks will track the presence or absence of the CSS and reload if it has changed.
One last thing: it is generally a good idea to add 'data-turbolinks-track': 'reload' to your application.css so that if you release a new version of your CSS, the users on the site will be up-to-date when the change goes live.
Hope that helps

For people who came here with a slightly different problem:
When using different CSS files for different areas of your application (e.g. application.css for your regular app and admin.css for your admin area), Turbolinks fails to handle them properly when they do not live on separate (sub)domains.
So when /admin uses a different CSS file than the rest of the application, clicking a link to, say, /admin/posts and then using the back button to navigate back to /, the wrong CSS file will be used.
In this case, you need to set a root location for Turbolinks.
From the docs:
By default, Turbolinks only loads URLs with the same origin — i.e. the same protocol, domain name, and port — as the current document. A visit to any other URL falls back to a full page load.
In some cases, you may want to further scope Turbolinks to a path on the same origin. For example, if your Turbolinks application lives at /app, and the non-Turbolinks help site lives at /help, links from the app to the help site shouldn’t use Turbolinks.
Include a <meta name="turbolinks-root"> element in your pages’ <head> to scope Turbolinks to a particular root location. Turbolinks will only load same-origin URLs that are prefixed with this path.
To make the admin area under /admin from my example display the CSS correctly, include <meta name="turbolinks-root" content="/admin"> in the layout's <head>.

Tried the same thing, reinstall Webpacker and still for the error
Webpacker can't find application in C:/Users/Admin/friends/public/packs/manifest.json. Possible causes:
You want to set webpacker.yml value of compile to true for your environment
unless you are using the webpack -w or the webpack-dev-server.
webpack has not yet re-run to reflect updates.
You have misconfigured Webpacker's config/webpacker.yml file.
Your webpack configuration is not creating a manifest.
Your manifest contains:
{
}

Related

Javascript method firing twice when using turbolink 5.2.0

Issue:
I have an E-commerce application built on Spree 3.7 and Rails 5.2, Right now I am facing turbolink(version 5.2.0) issue in which I have implemented javascript for adding items to the cart but js method firing twice and a similar item is being added into cart twice.
I have included following js in head tag-
<script>
<%= javascript_include_tag 'spree/frontend/all' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</script>
I have tried 'data-turbolinks-track': 'true/false' but my issue solved when removed
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>.
I read about turbolink from 'https://github.com/turbolinks/turbolink'. According to me turbolink is loading javascript method twice.
Any suggestions on how it can be solved?
After comment here is my application.js file
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require activestorage
//= require turbolinks
//= require cable
//= require jquery-ui/widgets/sortable
//= require wishlist
//= require product
//= require cart
Per your comment, you probably have two versions of compiled assets locally. Try running rake assets:clobber to clear out the additional assets.
So basically I was able to solve the issue, according to Turbolink our javascript should be wrapped in
document.addEventListener("turbolinks:load", function () { ... }
Our spree functions like addToCartForm etc. works on $( document ).ready()
So I have overridden those functions and wrapped in turbolinks:load, now everything is working fine.

Resource created as many times as accumulated requests

I have a really weird bug. I have a very simple Rails 4.2 app, and I was just starting to add some JavaScript functionality. I've started by adding a remote: true option to a form, but after that more than one resource are created in the database. It seems to have a criteria, though, and it is that the number of resources created equals the total amount of pages visited since the server started. So:
rails s and refresh the /new page, will create 1 resource.
Now visit page 1, page 2, page 3, and go back to /new and submit, and 4 resources are created.
Now visit page 5, page 6, go back to /new and submit and 7 resources are created.
As I have mentioned, I was just starting with JS, and only had another script that is not related with this in anyway (bug still happens if I remove this file and restart the server).
Just for reference, I've created a new Rails app and put remote: true to the form and, obviously, this is not happening, so something there is messing up my app.
I don't even know how to research this. Any clue on where should I start looking at?
EDIT: I've tried to reproduce the same situation in tests, using Capybara and doing several page visits before filling up a form, and I couldn't.
application.js
//= require jquery2
//= require jquery_ujs
//= require turbolinks
//= require_tree .
layouts/application.html.erb
Moved it to the end of file and added cache: true
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true, cache: true %>
</body>
</html>
Again: there was only one script in the app, and I've removed it. There are no more JS thing anywhere. None, at all.
I think the relevant question here is: how on earth can the number of page visits since the server was started be related to the number of resources created?
Thanks!
I can't yet believe it. It all was because of this:
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true, cache: true %>
</body>
</html>
I had to place the javascript tag back to its original place, within the <head> tag.
<head>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true, cache: true %>
</head>
Don't ask me why, but placing the javascript file at the bottom of the file caused all this mess.
EDIT:
Turns out this is something related with Turbolinks. Removing Turbolinks fixes the issue, and I can load all JS at the end of the document, again. See this issue on Turbolinks, and also this on someone's project.

Loading controller specific code

<%= javascript_include_tag "application", params[:controller] %>
I added the above tag in my application.html.erb, but it seems my js files are not loaded according to controller. When i navigate to localhost:8000/sessions it does not load sessions.js
Rails now uses the asset pipeline. In app/assets/javascripts/application.js you can require all your of javascript files with "magic comments":
//= require_tree .
Your javascript can now be inside app/assets/javascripts/sessions.js or even app/assets/javascripts/sessions.js.coffee if you want to use coffeescript.
Note that this will require all Javascript files on every page, which is often a desired effect because the client can cache the javascript and thus only has to download it at the first request. For more information read the Rails Guide I linked to above.
You can load controller specific js files as follows
<%= javascript_include_tag "application", controller_name %>
So that, if you navigate to localhost:8000/sessions it will load sessions.js file. And it is not necessary to add //= require_tree . in application.js.

Twitter Bootstrap and Rails: How to make some views responsive and others not

According to the bootstrap docs
adding the following to your <head> makes your site responsive
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="assets/css/bootstrap-responsive.css" rel="stylesheet">
In rails and the asset pipeline you declare your css file in application.css so the last line above is not required.
Im using the bootstrap-sass gem and the above line is achieved this line of code in the application.css file
#include "bootstrap-responsive";
It works!
But unfortunately this makes every view responsive.
I have a number of views such as my backbone app that I dont want to be responsive.
I thought about declaring the <meta viewport...> tag into a layout file that is only used for the those parts of my site that require responsive behavior.
This doesn't seem to work and despite some views not declaring this meta tag via their layout, they still become responsive.
Since I cant granularly control which css files get loaded in the asset pipeline I'm a bit stumped how to turn off and on this responsive behavior.
How do i achieve this?
Check out This link for some good info. It can be overwhelming, know, you don't have to do ALL of that... The key is: if you remove require tree (which will not add all files in directory) you need to manually add them in config/environments/production.rb with:
config.assets.precompile += %w( application-all.css application-print.css application-ie.css )
Then you can use stylesheet_link_tags with no issues...
To make it more flexible I add this to my application head:
<%= yield :head if content_for?(:head) %>
and then all my views use:
<% content_for(:head) do %>
<%= stylesheet_link_tag "#{params[:controller]}.#{params[:action]}" %>
<%= javascript_include_tag "#{params[:controller]}.#{params[:action]}" %>
<% end %>

Rails 3.1 and jQuery mobile: Best way to organize your JS & CSS while considering the asset pipeline?

I'm integrating my Rails 3.1 app with jQuery mobile (Beta 2, at the moment), and I'm uncertain how to organize my JS & CSS.
I have this in my application.mobile.erb's head tag (copied right from http://jquerymobile.com/download/):
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.css" />
<script src="http://code.jquery.com/jquery-1.6.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.js"></script>
Should I put my stylesheet_link_tag for 'application' right above this so my CSS styles don't override jQuery mobile's fancy CSS? What about the javascript_include_tag for 'application'?
Or maybe all of this should be entirely separate?
I'm just unsure how to organize all of this / if there is a conventional way to do this. Input appreciated.
(Please ask for more details if you need any.)
EDIT:
*I'm also wondering where to put my mobile-specific JS and CSS...
There is now a jQuery Mobile Ruby gem that will make the jQuery Mobile files available to you in the assets pipeline.
Installation is easy. Simply add the gem to your apps Gemfile
gem "jquery-mobile-rails"
and run bundle install. Then, you can add
//= require jquery.mobile
to your application.js or wherever else you want to include the files.
Just like you, I was quite confused to figure out how to use jQuery Mobile (now final 1.0) with Rails 3.1's new asset pipeline.
First, drop jquery.mobile.js and jquery.mobile.css into assets/javascripts and assets/stylesheets respectively.
Second, insert "require jquery.mobile" into your application.js manifest
//= require jquery
//= require jquery_ujs
//= require jquery.mobile
And the same to your application.css manifest:
*= require_self
*= require_tree .
*= require jquery.mobile
Third, put "application.js" and "application.css" into the layout, application.html.erb
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= javascript_include_tag "application" %>
<%= stylesheet_link_tag "application" %>
<%= csrf_meta_tags %>
Fourth, don't forget to add 'meta name~~~' line to make it work properly.
<meta content="width=device-width, minimum-scale=1, maximum-scale=1" name="viewport">
Also use the jQuery mobile properties properly, like 'data-role=”page”' in the page.
Others recommend to use gems like 'jquery-mobile-rails' or similar but I wouldn't.
It's really your decision on what you want to have precedence. Some things may have to have precedence over others just based on the order you call things (if a function is being called in file2, make sure file1 that defines that function is included before it).
In terms of how to work this in with asset_pipeline, you either download the assets yourself and bundle them in application.css/application.js or you keep it in <head> in the order that works for you.

Resources