1

I'm diving into Ruby on Rails and I'm building an app that uses Rails 3.2.8. I'm still learning to use the Asset Pipeline, but I'm already running into a problem. I have my Javascript files organized and named by the different pages in my website (i.e. home.html -> home.js, parts.html -> parts.js), but my Rails app is loading all my Javascript files and one of my Javascript files is crashing because it's referencing elements that don't exist on the page that's loaded (home.html)...

"uncaught exception: jsobj.edit can't find div #parts_list"

Following the online documentation, I'm including in the manifest all the JS files that are needed in my app...

//= require modernizr-latest
//= require jquery
//= require jquery_ujs
//= require home
//= require parts
//= require_tree .

...so when I load the home page, the parts.js files is loaded and executed and crashing since the parts_list div doesn't exist on the homepage.

My questions are...

  1. Should I attempt to address this problem at the Javascript level? If so, how?
  2. Or should I attempt to fix it at the Rails level and only include Javascript files that should be running at any given time. Again, if so, how can I approach this?
  3. This seems like this would be a fairly common problem. Am I'm not using Rails correctly?

Thanks so much in advance for your wisdom!

cweiske
  • 30,033
  • 14
  • 133
  • 194
BeachRunnerFred
  • 18,070
  • 35
  • 139
  • 238
  • [Look here](http://stackoverflow.com/questions/6167805/using-rails-3-1-where-do-you-put-your-page-specific-javascript-code) – Trent Earl Dec 01 '12 at 03:17

3 Answers3

4

To include specific javascript files into specific view pages only, you need to go with the following procedure.

i) In the assets folder create a separate folder eg. 'separate_view' , and inside put your specific js, and css files.

ii) In the application lay out write like following for 'separate_view'.
  <%= yield :separate_view %>

iii) In your target template write the following for 'separate_view'.
  <% content_for (:separate_view) do %>
    <%= javascript_include_tag "xxx.js" %>
    <%= stylesheet_link_tag "xxx.css" %>
  <%end%>


The above will go fine with your specific view files.

VenkatK
  • 1,295
  • 1
  • 9
  • 21
  • In addition if you are starting with a default generated rails app you will need to either remove the 'require_tree .' from app/assets/javascripts/application.js or remove the "javascript_include_tag 'application'" from your layout. – Mark Fraser Dec 01 '12 at 09:35
  • this is a great solution, it gives me complete control at the view level, perfect! Here's a link to an example http://stackoverflow.com/questions/7312465/how-to-display-controller-specific-javascript-in-rails-3-1 – BeachRunnerFred Dec 01 '12 at 17:43
1

To answer your questions:

  1. You could do it this way, but it's not strictly necessary, and you can load assets on a per-view basis so you can get them loaded only when you want to. The key is understanding the manifest file you've got there, and when it's loaded.
  2. Yes, do this. RailsCasts episode #279 explains the loading of assets. It also touches on how to separate out your assets to only be loaded when you need them. The short version is that the manifest file is loaded in your layout, so if you use a different layout for different sections of your site, you can control which assets are loaded for which views fairly easily.
  3. You're using Rails correctly, but learning the AssetPipeline is a common, sometimes steep learning curve for a lot of people. That Railscast episode, and a lot of practice, is my best recommendation.
jefflunt
  • 33,527
  • 7
  • 88
  • 126
  • I watched the video, but it didn't mention anything about layouts. It just show how to exclude certain JS files by putting them into a subdirectory, but it never showed how to include those files in the subdirectory for certain pages. Your thoughts? I'll begin researching layouts. – BeachRunnerFred Dec 01 '12 at 03:40
  • Look in `app/views/layouts` and note that it makes a call to something like `javascript_include_tag "application"` - note that "application" probably matches the name of your `assets/javascript/application.js` file - the manifest file. The `javascript_include_tag` in the layout is what loads the manifest. – jefflunt Dec 01 '12 at 03:48
  • Also, [the guide to layouts and rendering a view](http://guides.rubyonrails.org/layouts_and_rendering.html) – jefflunt Dec 01 '12 at 03:49
0
  1. Yes. You should solve this by not relying on DOM elements to be present when script loads. Typically, scripts are declared at the top of the page and therefore they load BEFORE any of the DOM elements are rendered by the browser. If you are relying on DOM to be present at the time script executes, you are bound to have problems. Instead, you should fix that by wrapping functionality in question into a method / function and executing this function on $(document).ready or by binding live() events

  2. Yes. You can fix that by building multiple manifest files (instead of one gigantic application.js that is included by default)

  3. This problem is commonly solved by combination of (1) and (2)

Dmitry Frenkel
  • 1,708
  • 11
  • 17
  • Thanks, Dmitry! Tho I am wrapping the JS code in the $(document).ready block. The problem isn't trying to access elements before they're ready, the problem is trying to access elements that don't exist on the page that's being loaded. I'm looking into approach #2 right now. – BeachRunnerFred Dec 01 '12 at 03:20