sprockets icon indicating copy to clipboard operation
sprockets copied to clipboard

Unexpected require path, given the current documentation

Open carols10cents opened this issue 9 years ago • 5 comments

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:precompile and 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.js and added this to application.js (https://github.com/carols10cents/sprockets-test-app/commit/8abff570b61a9e84e245efb66e1f90f7910c276e):
//= require d/e
  • I again ran rake assets:precompile and 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/e to just require e and that errored as I would have originally expected, but after other_javascripts/f could be referenced just with f, 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

carols10cents avatar Feb 24 '16 21:02 carols10cents

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.

schneems avatar Feb 24 '16 22:02 schneems

You can add a load path like this http://stackoverflow.com/questions/14735635/add-folder-to-asset-pipeline-path

schneems avatar Feb 24 '16 22:02 schneems

@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?"

matthewd avatar Feb 24 '16 22:02 matthewd

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

carols10cents avatar Feb 24 '16 22:02 carols10cents

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 :)

carols10cents avatar Feb 24 '16 22:02 carols10cents