Unexpected require path, given the current documentation
This might just be a documentation issue, but this left me pretty confused. So here's a dramatic re-enactment of what happened:
- I created a brand new Rails 4.2.5.1 app, which got me sprockets 3.5.2 (https://github.com/carols10cents/sprockets-test-app/commit/ad4b57037bf64bb6d2949ae8b7f33e99f7e9c668).
- I read the comment at the top of app/assets/javascripts/application.js, which says:
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
- Ok, cool. So to test this out, I created files app/assets/javascripts/a.js, lib/assets/javascripts/b.js, and vendor/assets/javascripts/c.js, and added this to application.js (https://github.com/carols10cents/sprockets-test-app/commit/54dc30517694bb0e06d5eadd566d19ede917fd6c):
//= require a
//= require b
//= require c
- I ran
rake assets:precompileand it completed successfully, and had the contents of a, b, and c in the compiled application.js. So far so good. - I then created the file
app/assets/javascripts/d/e.jsand added this to application.js (https://github.com/carols10cents/sprockets-test-app/commit/8abff570b61a9e84e245efb66e1f90f7910c276e):
//= require d/e
- I again ran
rake assets:precompileand it again completed successfully, and the contents of e.js were in the compiled application.js. Ok, cool. - Now, I created
app/assets/other_javascripts/f.js(note that the other_javascripts is a sibling directory of app/assets/javascripts, not a subdirectory) and I referenced it with a relative path in application.js:
require ../other_javascripts/f
- Running `rake assets:precompile at this point gives me this error:
Sprockets::FileNotFound: couldn't find file '../other_javascripts/f'
under
'/Users/carolnichols/Ruby/sprockets-test-app/app/assets/javascripts'
with type 'application/javascript'
- And now I am sad because I thought the comment meant a relative path would work.
- Next I tried changing that line to
require other_javascripts/f, which gives me a slightly different error:
Sprockets::FileNotFound: couldn't find file 'other_javascripts/f' with
type 'application/javascript'
- And then, just for fun, I tried changing that line to just
require f, and... SURPRISE! That works!! (https://github.com/carols10cents/sprockets-test-app/commit/cb1315e645e5f2118776caf62b6667f7cbe323b5) This is really unexpected, and the docs definitely didn't lead me there, I was just guessing. - Still experimenting, I tried changing
require d/eto justrequire eand that errored as I would have originally expected, but afterother_javascripts/fcould be referenced just withf, I kind of expected it to work. The error I get with that is:
Sprockets::FileNotFound: couldn't find file 'e' with type 'application/javascript'
- Looking for some more clarity, I followed the link to the sprockets readme that's also in the comment in application.js: https://github.com/rails/sprockets#sprockets-directives. That currently says:
For directives that take a path argument, you may specify either a logical path or a relative path. Relative paths begin with ./ and reference files relative to the location of the current file.
The require Directive
require path inserts the contents of the asset source file specified by path. If the file is required multiple times, it will appear in the bundle only once.
- This gives me one more thing to try:
require ./../other_javascripts/f, since it says "Relative paths begin with ./ and reference files relative to the location of the current file.". Alas:
Sprockets::FileNotFound: couldn't find file './../other_javascripts/f' under '/Users/carolnichols/Ruby/sprockets-test-app/app/assets/javascripts' with type 'application/javascript'
One more thing: I lied. I wasn't creating a brand new app. I'm trying to upgrade an existing app from using sprockets 2.12 to using sprockets 3.5. require ../other_javascripts/f works totally fine with sprockets 2.12.4 (https://github.com/carols10cents/sprockets-test-app/commit/cf4bd8a68b722d768fd4094463a9e7b112afd8ca) (incidentally, require f works with sprockets 2.12.4 as well but our existing code was the other way) and I didn't see anything in https://github.com/rails/sprockets/blob/3.x/UPGRADING.md about paths like '../other_javascripts/f' needing to be updated :-/
If this is indeed deemed just a documentation issue, I can try adding the docs that would have helped me-- but I do want to make sure this isn't a bug first :)
Thank you!! <3 <3 <3
I think this is because other_javascripts folder isn't registered in the load path, which is silly because you're telling it EXACTLY where it is. I think this is done to prevent unintentional file access. We should add something like
Searched in [<path>, <path>, <path>]
To the error message.
You can add a load path like this http://stackoverflow.com/questions/14735635/add-folder-to-asset-pipeline-path
@schneems it is in the load path -- that's why a straight f will find it.
Enumerating the paths we searched would certainly clarify the behaviour, but might be quite the flood of information: in an average setup, there are a lot of directories on the load path.
One thought: what if we enumerated the logical path to every known asset with a matching basename? (only in debug, of course)
So even if you tried to include ../../../totally/wrong/path/e, we'd offer "Maybe you meant: d/e or something/else/e?"
Hi @schneems !
I think this is because other_javascripts folder isn't registered in the load path, which is silly because you're telling it EXACTLY where it is. I think this is done to prevent unintentional file access.
If other_javascripts isn't in the load path, why DOES sprockets find other_javascripts/f if I just say require f (see https://github.com/carols10cents/sprockets-test-app/commit/cb1315e645e5f2118776caf62b6667f7cbe323b5)? That's not preventing unintentional file access at all :(
We should add something like
Searched in [
, , ] To the error message.
I totally agree :) https://github.com/rails/sprockets/issues/252
One thought: what if we enumerated the logical path to every known asset with a matching basename? (only in debug, of course)
So even if you tried to include ../../../totally/wrong/path/e, we'd offer "Maybe you meant: d/e or something/else/e?"
That would also be incredible :)