Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a good way of implementing per-page JavaScript in Rails?

Trying new things in Ruby - on each page I'm doing very rich stuff with jquery. Obviously if I put all the jquery into application.js it's going to grow very large very quickly.

Is it a good approach to lazy-load a page-specific js file at the end? eg:

<script>

$(document).ready(function() {

  $.getScript("/javascripts/this_pages_scripts.js");

});
</script>

Is there a rails-way way of doing this? I am aware of the new.js.erb etc. files and ujs, but I am still talking about more page-specific js - you know, drag and drop initialisers, dialog creators, etc.

Thank you very much.

like image 220
Dave Avatar asked Apr 08 '11 14:04

Dave


People also ask

Where do I put JavaScript code in Rails?

The directory structure for JavaScript has changed to the app/javascript/packs/ folder. In that folder you will find the application. js file, which is just like the application.

How do I enable JavaScript in Rails?

1 Import maps js or Yarn to function. If you plan to use Rails with importmap-rails to manage your JavaScript dependencies, there is no need to install Node. js or Yarn. When using import maps, no separate build process is required, just start your server with bin/rails server and you are good to go.

What is Rails Ujs?

Rails UJS (Unobtrusive JavaScript) is the JavaScript library that helps Rails do its magic when we use options like remote: true for many of the html helpers. In this article I'll try to explain the main concept of how this works to make it transparent for the user.


1 Answers

There are two ways that I use:

For tiny, trivial scripts that are just adding a bit of eye-candy, I often include them inline in the template they modify (just like you've shown), because it is easier for me to keep track of this way.

For anything that's more than one or two little lines I keep it unobtrusive, but load it using content_for

My Application Layout looks like this (in HAML):

= javascript_include_tag 'jquery.144.min','rails','jquery.tools','application'
= yield :scripts

The important part is yield :scripts. Then in a page where I need some javascript I do:

- content_for :scripts do
  = javascript_include_tag 'photo_form'

This loads the javascript in the header, but only if the given template is shown. content_for sends stuff to the yield method with the corresponding name.

You can stick a yield block like that anywhere -- I also have one just before the closing body tag. Yield / content_for is really handy.

Note as tadman pointed out in the comments, anything that doesn't have to be loaded in the head should be loaded at the end of the page.

One last thing to be aware of, if you have something more complex you can also use instance variables between your templates and your application view. For instance, I have a menubar in my app that's in the application layout. So, sometimes I want to trigger a context-specific button or additional row of buttons only on certain pages.

In my application layout I call a partial which renders the menu, the menu code looks like:

#menubar (normal menu stuff)
  - if @special_menu
    #special_menu

So, then in any template you can do:

- @special_menu = true

... and for that page the given menu will appear. You can also do this in controller actions, I have one controller where I added a before filter that sets one of the menu flags to true. You could do the same thing for any complex set of javascript stuff you might want to conditionally include.

Most of these ideas I got from watching this railscast: http://railscasts.com/episodes/30-pretty-page-title

You should take a look!

like image 118
Andrew Avatar answered Oct 14 '22 03:10

Andrew