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.
Related
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.
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:
{
}
So, I'm learning to build Rails app, I've written the controller and everything looks fine, then moved to get the views.
As usual I downloaded a template and started to move it into my app (normal html template from html5up.net).
All JS files I've put them in app/assets/javascripts.
All CSS files I've put them in the app/assets/stylesheets.
and in the app/views/layouts/application.html.erb I've included them all using the javascript_include_tag and stylesheet_link_tag
so everything in theory should be fine.
In my routes file I got those 2 lines:
resources :users
root 'users#new'
When I start the server and go to the root route localhost:3000 everything is rendered smoothly and with awesome style, however if I try to access the very same page but from it's original route localhost:3000/users/new somewhy the html I get doesn't include images and scripts, and the style is messed up (probably because no images/js), same goes for other pages from the users controller.
I tried putting the js/css files in public folder and linking to them but it gives exact same results.
Any idea what's going wrong and how to fix it?
I'm using Rails 4.2.1
Rather than including each of the stylesheets / javascripts directly, reference them within application.css and application.js respectively. This will add them to the asset pipeline - making the application run faster amongst other things (http://guides.rubyonrails.org/asset_pipeline.html).
So instead of referencing the scripts directly in application.html.erb, just ensure application.html.erb has these to lines in the head section:
<%= stylesheet_link_tag "application", media: "all" %>
<%= javascript_include_tag "application" %>
Then check that application.css exists in app/assets/stylesheets and that it includes this line:
*= require_tree .
This tells it to include every .css file that is within the assets/stylesheets directory (alternatively reference each file individually with a require statement)
Similarly, ensure app/assests/javascripts/application.js includes:
//= require require_tree .
And that the javascript files are in app/assets/javascripts
Put all the images in app/assets/images
Change all the references to the images in CSS files from
url("images/example.png")
to
url(image_path("example.jpg"))
or
image-url("example.png")
And you should be good to go... the rails helpers should handle the relative path issues that it looks like you've been experiencing.
I know it's kinda old, but forgot to post the answer for this.
The problem was in the view html codes, the <%= stylesheet_link_tag "application", media: "all" %> was inside a <noscript> tags so they didn't work.
My problem
I realize that there are a ton of questions about using remote: true and having the server process the request as HTML instead of javascript so that you get a MissingTemplate Error on SO already.
So far none of them answer my question. To prove that:
I know that I have included / bundled etc jquery, jquery-ujs etc because this link used to work. Also I can see them getting included on the rendered page and also as mentioned in the question, I'm getting the server to successfully process the request as JS in many places.
I know that I'm not having a precompiled assets issue because I don't have any precompiled assets (deleted the public/assets folder myself just to make sure).
If I put the following on my index page right at the top
<%= link_to "Test", "/create_tags_dialog", :remote => true %>
It renders the html perfectly:
<a data-remote="true" href="/create_tags_dialog">Test</a>
and correctly calls the remote script, no TemplateMissing Error because the request is processed as JS.
Just to be sure I even copied the rendered HTML back onto the index and they both work as expected:
<a data-remote="true" href="/create_tags_dialog">Test2</a>
(i.e. the server processes the request as JS and I get no TemplateMissing Error)
Now for the problem
If I put the same link_to line into a bootstrap dropdown <ul> the request gets processed as HTML and I get a MissingTemplate Error. I checked and the rendered html is identical! Again, just to check, I put the raw html in as well <a data-remote="true" href="/create_tags_dialog">Test</a>
The only difference between identical uses of this anchor tag is that the second use (the broken one) is inside of a bootstrap dropdown which gets rendered as a partial on page load.
Could it be the partial? Please let me know if I can include any outputs, error logs, screenshots etc to help clarify things.
Note
I see a few solutions like this one
Which recommend ensuring this line is in the index
<%= javascript_include_tag "jquery", "jquery_ujs" %>
I don't have that line exactly, mine is
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
and my application.js is
//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require bootstrap.min
//= require turbolinks
//= require jquery-readyselector
//= require fastclick
//= require_tree .
Also the link is working in a different div of the same page at the same time, but just in case I thought I'd mention this. . .
Update
Thanks to AmShaegar I discovered the change in my code that causes this to break. I added a stopPropagation() to my dropdowns because I want them to stay open after click like this:
$('#tags-filter-dropdown').click (e) ->
e.stopPropagation()
If I comment this out, my remote-link goes back to working. Any suggestions for how I can both keep that dropdown from closing and activate a remote link? I tried implementing AmShaegar's solution of giving the link a class and preventing propagation / default on the link specifically but it just killed the link (unresponsive). Is there a middle ground?
Based on this question and my comment above:
It may help if you disable bootstraps onclick handler for your remote link. You need to give your link a special class and then write your own onclick handler.
link_to "Test", "/create_tags_dialog", :remote => true, { class: 'no_bootstrap' }
$(".no_bootstrap").click(function(e) {
e.stopPropagation();
e.preventDefault();
// You may still want to close the drop down manually here.
// See bootstrap documentation for this.
});
Update
Looks like you need to trigger the remote click event manually after you stopped propagation. Therefor you need to know how rails does it internally.
From viewing the source code I would say this could work like this:
$(".no_bootstrap").click(function(e) {
e.stopPropagation();
e.preventDefault();
$(e.target).trigger('click.rails');
});
I have a Rails 4 app with turbo-links enabled, but I can't get the meta tags to refresh when changing the page ( not a full refresh ) . I read that the meta-tags need to be included before the javascript that loads the turbo-links but it has no effect. A full refresh does the job, but unfortunately this is not what i search for.
layout/application.html.haml
%html
%head
%title= "Title"
- if content_for?(:meta_description)
%meta{content: (yield :meta_description), name: "description"}/
%meta{content: (yield :meta_keywords), name: "keywords"}/
= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true
= javascript_include_tag "application", "data-turbolinks-track" => true
= csrf_meta_tags
%body{class: params[:controller].gsub("/", "-"), id: 'top'}
= render "shared/header"
.body-content
= render "shared/flash"
= yield
= render "shared/footer"
= render "shared/analytics"
helpers/application_helper.rb
def meta_tag(title, description)
content_for :meta_keywords do
title
end
content_for :meta_description do
description
end
end
And this is how I call them
= meta_tag('here s my title', 'and the keywords')
Thanks
How Turbolinks works
Turbolinks is designed to keep the <head> tag the same and merely replaces the <body> tag with the contents of the requested page via an AJAX request. Since your <meta> tags are located in the <head>, they won't be changed via a Turbolinks request.
What about SEO?
From an SEO perspective, you don't need to worry about the <meta> tags being updated on a Turbolinks request because the search engine crawlers will always do a full page request and won't execute the Turbolinks javascript.
From a user's perspective, the only tag in the <head> that needs to change for each request is the <title> tag, so special handling for that was built-in to Turbolinks itself.
Will this behavior ever change?
This "issue" has been raised and shot down a couple times, each time being declared a non-issue by DHH himself, so I wouldn't count on this behavior changing any time soon.
See:
https://github.com/rails/turbolinks/issues/81
https://github.com/rails/turbolinks/pull/165
It's a TurboLinks Problem
By design, Turbolinks basically keeps the <head> of your page the same & calls the <body> of your document via ajax if it's going to remain the same (you're using the same controller / action). It's some crazy thing to maintain application performance
Here is a good explanation of Turbolinks
I've had a similar problem to this with Javascript, and was able to use the Jquery-Turbolinks gem to keep JS rendering
For your meta tags, although I don't know a solution off hand, I managed to find a decent gem you might benefit from: MetaMagic. It allows you to define meta tags in the view, kind of like how the content_block facility works. This should be loaded on every http request
I extend the current turbolinks js ;)
It will replace meta tags and canonical link!
https://github.com/philklei/turbolinks
Have a look on meta-tags gem
"Using with pjax" section