Reputation: 1985
I'm using Rails 3.2, and am somewhat confused about the handling of subdirectories and relative paths of the asset pipeline.
I'm trying to include four code files in (javascripts/edit
), one of them being in the subdirectory javascripts/edit/ckeditor
, in a manifest file, (javascripts/edit/all.js
). I'm not including these in the application.js because I want to include these scripts only on certain pages.
Doing //= require ckeditor/ckeditor
doesn't work. Doing //= require mycode
(to require javascripts/edit/mycode.js
), too, doesn't work, apparently because mycode.js is in the "edit" subdirectory of the javascripts "root" folder. To make it work, I had to put this:
//= require ./ckeditor/ckeditor
//= require ./json2
//= require ./cssjson
//= require ./mycode
inside of my manifest all.js
. Note that this:
//= require edit/ckeditor/ckeditor
//= require edit/json2
//= require edit/cssjson
//= require edit/mycode
works exactly the same, even though all.js
itself is already in the edit
subdirectory.
So my question is, why does this work this way? I would expect to be able to put manifest files in subdirectories and just include files that are in that same subdirectory (e.g. //= require json2
), but apparently, all //= require
directives in any file below app/assets/javascripts
always are relative to that "root" folder, not the subdirectory that the manifest files are in.
Upvotes: 1
Views: 150
Reputation: 76774
So my question is, why does this work this way?
Because when Rails compiles the assets, it's compiling from a central point, not your subdirectory. The manifest system works based on the assets' root path (the documentation says The first feature of the pipeline is to concatenate assets
), consequently your assets will be compiled from the application.js
file
You have to remember when Rails runs, it's not loading the assets dynamically. It's designed to load application.css
/ application.js
all the time, and it's then up to the developer to delegate assets which they wish to load on specific pages
The way we do this is to include all the "constant" files in our application.js
file, and then load controller-specific assets in the layout. This allows us to only call things like JQuery all the time, whilst we may call specific JQuery plugins for certain controllers:
Including The Right Assets In The Right Places
This is what we do:
#app/views/layouts/application.html.erb
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= stylesheet_link_tag controller_name, media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag controller_name, "data-turbolinks-track" => true %>
#app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
//= require jquery.ui.draggable
//= require_tree ./jquery
//= require_tree ./extra
//= require turbolinks
#app/assets/javascripts/users.js.erb
//= require ** anything you want **
This allows you to have a lot more control over which assets you're loading
Upvotes: 2