-
Notifications
You must be signed in to change notification settings - Fork 428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent adding existing autoload_paths #1383
Prevent adding existing autoload_paths #1383
Conversation
1eb70e2
to
abba185
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thutterer thanks for taking the time to propose this PR. I'm curious to see the sandbox application in test
updated to reproduce and thus necessitate this change. Mind giving that a shot?
I've tried a couple of things over the last few days, but haven't yet found a good way to test the initializer code without seriously messing with the sandbox application. The reason why this is tricky is that this code change is only required when zeitwerk gets loaded before the initializers run. See here for more information why one might do that, but basically:
AFAIU, I'd either need a whole new sandbox just for this test, or change the sandbox in a way that affects all tests, which is not what I want either. As an alternative approach I've tried to move the code of the initializer into a method. I thought I then can at least unit-test the method, but when minitest is ready, zeitwerk already froze the autoload path, even in the current default setup. I had a look through the test suite though, and custom preview paths are already thoroughly tested and these tests didn't break with my change. So would you consider merging this PR without additional tests? |
@thutterer thanks for looking into writing tests for this change. I'm feeling torn here so perhaps I can share some more thoughts and you can let me know what you think. First and foremost, we try really hard on this project to make sure that any change we introduce cannot be unintentionally reverted. This allows us to more readily accept community contributions knowing that if CI passes, we won't be breaking any intended behaviors. This approach has generally served us well. Second, I'm wondering why this has yet to come up until now. My gut says it might be due to an unusual application configuration on your end? In this case I do believe that adding another test application would be the way forward. It will help us identify if the use case is something we want to support in the framework and will add a backstop from this change regressing in the future. |
@joelhawksley Thank you for taking the time to look into this and share you thoughts. Much appreciated, especially as this is fixing such a specific corner case situation.
100% agree with this approach.
It is definitely not the Rails default what we do here, but I don't know how unusual it really is. Let me explain: Our app started long before Zeitwerk replaced the old autoloading mechanics in Rails. But at that point we already had a lot of autoloaded constants in our initializers, so we had to move the loading of Zeitwerk earlier than these initializers. But a side-effect of this is that in the initializers, I'd bet some other older Rails apps faced the same challenge and might have solved it the same way we did. They would all have the same issue. Probably they just haven't started to use ViewComponent previews yet 😉
OK, I will try that, but it will take me a couple of days to get to it. Also, I'm a bit concerned that the test setup for this change will be literally 100x more (in LOC and complexity) than the change itself, making the "not worth the added project complexity for such a corner case" argument to not merge this even stronger. So would it maybe sufficient to explain the change in a code comment? I know it's not ideal, but my reasoning here is that the change is so self-contained in the initializer code that it's close to impossible to break it without touching the code itself, where a comment then would make it clear why this approach was taken. What do you think? |
@thutterer thank you for your thorough reply ❤️. I'd be happy to merge this with a comment if you can add a regression test as a fast follow, but only if this is a blocker for you. I'm about to travel for holiday and Brighton Ruby so my responses will be delayed until July 😄 |
77533ca
to
3c31350
Compare
@joelhawksley Turns out I was totally overthinking this... no special setup required to test this new behavior. I've added a simple regression test now. Please have a look whenever it's convenient, no rush. Have fun in 🇬🇧! |
3c31350
to
27da458
Compare
Very nice! Thank you for your patience in getting this landed ❤️ |
* Prevent adding duplicates to autoload_paths * Add thutterer to contributors list
* Prevent adding duplicates to autoload_paths * Add thutterer to contributors list
What are you trying to accomplish?
This prevents the
set_autoload_paths
initializer to add paths intoActiveSupport::Dependencies.autoload_paths
that are already in there.This is likely a non-issue for most projects, and ActiveSupport handles this, I assume. But I ran into this in a codebase where the
ActiveSupport::Dependencies.autoload_paths
array is already frozen when theview_component.set_autoload_paths
initializer does its thing.With this change, it is possible to manually add the preview paths to the autoload paths like this:
The
set_autoload_paths
initializer then has nopaths_to_add
and doesn't touch the (maybe frozen)ActiveSupport::Dependencies.autoload_paths
.What approach did you choose and why?
I first thought Array's
union
method would be the perfect replacement forconcat
but it's not as it returns a new array instead of making the change on the original. That's why I now chose a more verbose approach with a variable for the diff. That should also make it easy to read and understand the code.Anything you want to highlight for special attention from reviewers?
I couldn't find a good place to add/update a spec for this. Please advise if/where to do that. Thanks!