Comments (13)
I think I have it.
Essentially, what is happening is that eager loading is implemented as a breadth-first recursion calling require
, and that is not consistent with the logic while setting autoloads that discards late files with the same relative name mimicking $LOAD_PATH
semantics.
The reason is that by design we use only absolute file names, and both require
calls succeed because the file names are different, so the one in devise wins because it runs later.
The gist of the problem is shown here:
$ cat a/foo.rb
Foo = :a
$ cat b/foo.rb
Foo = :b
$ cat test.rb
require "zeitwerk"
$VERBOSE = nil
lA = Zeitwerk::Loader.new
lA.push_dir("a")
lA.setup
lB = Zeitwerk::Loader.new
lB.push_dir("b")
lB.setup
p Foo
lA.reload
lB.reload
lA.eager_load
lB.eager_load
p Foo
The output of the test is
:a
:b
which is not consistent, it should print :a
twice.
In the early prototypes of Zeitwerk I mantained a structure with constants to be loaded, and triggered autoloads instead of using require
, it could be the case that I might need to go back to that initial implementation.
I'll think how to address it, but we'll do something.
from zeitwerk.
Could you please try branch eager-load-skip
? I have drafted a fix.
from zeitwerk.
I deleted the previous comment. I have been able to reproduce now the steps above and the DeviseHelper
module from the app gets the autoload set first. Need to investigate with the real thing.
from zeitwerk.
Thanks for checking it out @fxn! My first assumption was that basically that I was doing thing module override wrong, like you mentioned in your previous comment. Then we found it strange that things were different with eager_load on and off since it wasn't consistent. Curious to learn what's going on. 👍
from zeitwerk.
@fxn that works for me!
@excid3 did you want to give it a try?
from zeitwerk.
Worked perfect. Thanks @fxn, that was quick!
from zeitwerk.
I think I may have found another "bug".
If you set config.eager_load = false
run it in development with 'foreman start' and once it starts up add this line after_action { pp 'foo' }
to app/controllers/application_controller.rb
; refresh the page and you will notice foo
does not get logged.
If you repeat the previous steps (delete that line added to application.rb first) and before running foreman start
set config.autoloader = :classic
, when you add that line in now and refresh the page it will print out foo
just fine.
from zeitwerk.
Regarding eager loading, I'll polish the code and publish a new version of the gem.
The issue @cj mentions seems different (and surprising!), maybe deserves a different ticket. Did you restart the server after changing the configuration? If yes, could you please enable logging in config/application.rb
:
Rails.autoloaders.logger = method(:puts)
reproduce, and share the entire log specifying at which point did you change and reload?
from zeitwerk.
@cj just in case... do you have config.cache_classes
set to false
? It should be for reloading to work.
from zeitwerk.
@fxn I can open up a new ticket if you would like.
I'm using the same template as used in this issue which is rails new myapp -d postgresql -m https://raw.githubusercontent.com/excid3/jumpstart/c6c0de0/template.rb
it creates a standard config/environments/development.rb
file with the contents of https://gist.github.com/cj/45d48da8b7bfbd11bbaaacb04abd6ff8 where config.cache_classes
is indeed false.
When I say, "it does not get logged", I mean it does not get printed out in the console where the command foreman start
was ran.
I am adding this line after_action { pp 'foo' }
to app/controllers/application_controller.rb
after the rails server has started and finished loading from running foreman start
. When I refresh the browser I should see foo
printed to the console where foreman is running, but I do not. If however I kill foreman, remove the line I added after_action { pp 'foo' }
and add config.autoloader = :classic
to config/environments/development.rb
, start the server back up with foreman start
and add back in the line after_action { pp 'foo' }
to app/controllers/application_controller.rb
; refresh the browser, I see foo
printed out to the console as expected.
I hope this makes sense, if you need me to record a screencast or go in to more detail let me know.
from zeitwerk.
One other thing to note is I have spring disabled (http://fuzzyblog.io/blog/rails/2017/03/20/disabling-spring-in-rails.html).
from zeitwerk.
@cj did you see the comment above re printing Zeitwerk traces?
Yeah, better create a new ticket for this one please.
from zeitwerk.
The just published 1.3.4 has this solved, thanks for the bug report!
from zeitwerk.
Related Issues (20)
- Public API that resolves constants for a given filename HOT 9
- Using Zeitwerk in gem development HOT 8
- Unlucky raise by rack-timeout causes missing constant HOT 3
- Zeitwerk not loading children of struct namespaces HOT 5
- Zeitwerk not autoload the middleware directory HOT 2
- Zeitwerk, omniauth and multiple DBs (connects_to) HOT 9
- (Re-)Loading modules defined as a root namespace HOT 2
- Ruby 3.3.0-rc1 warning issues HOT 3
- Gemfile/gemspec csv HOT 2
- Getting the source location of a constant while loading it HOT 12
- Gem's loader is being setup multiple times HOT 24
- Autoloading not working in rake task HOT 4
- Zeitwerk::NameError on calling Zeitwerk::Loader.eager_load_all HOT 11
- Deprecation message coming from zeitwerk HOT 2
- Reloading of local gems HOT 27
- drb was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0 HOT 3
- Ruby 3.4.0 no longer includes "abbrev" and it suggests zeitwerk to include it HOT 2
- Error when using in Ractor HOT 3
- Namespaced concerns don't load HOT 33
- Zeitwerk::NameError for gem VERSION HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from zeitwerk.