Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix routes being cleared when using
reload_routes!
:
- Pretty sure it fixes rails#54297 and rails#53205, but both issues didn't provide enough information. - When using `Rails.application.reload_routes!` (which is public API), in certain conditions, it is possible that this will clear almost all routes in the routeset. The line of code making this happen is this one https://github.com/rails/rails/blob/38e9a72db45842d1d2f05fb2272df3a10225f981/actionpack/lib/action_dispatch/routing/route_set.rb#L460. That flag is supposed to be `true` for the entire duration of evaluating a route file. This was the case before rails#53522, which introduced the issue. It indirectly resets that flag to false because of a recursion. This is a summary of the code order execution when calling `Rails.application.reload_routes`: 1) The RouteSet sets the `disable_clear_and_finalize` flag to false, so that no routes gets cleared in between multiple call to `Rails.application.routes.draw`. 2) All route files get evaluated, and any call to `Rails.application.routes.draw` gets picked up. 3) We enter a recursion because the RouteSet in development is a LazyRouteSet which when calling `draw` reloads the route. [here](https://github.com/rails/rails/blob/38e9a72db45842d1d2f05fb2272df3a10225f981/railties/lib/rails/engine/lazy_route_set.rb#L72) and [here](https://github.com/rails/rails/blob/38e9a72db45842d1d2f05fb2272df3a10225f981/railties/lib/rails/application.rb#L163) 4) The route file get evaluated again, the `disable_clear_and_finalize` is reset to false, we exit the recursion and continue where we were. 5) The `disable_clear_and_finalize` is now false, any call to `Rails.application.draw` now resets all routes before it gets evaluated. Which basically means the very last one would have effect. ------------------------ I can only think of two way where `reload_routes` may cause a issue: - Inside a Rake task - Inside a middleware This is because the application needs to be initialized and the routeset never evaluated in order to trigger the bug. railsware/js-routes#320 and amatsuda/traceroute#49 confirms it. ## Solution When calling `reload_routes!`, if the routes were never loaded, load them and set the `loaded` flag. Otherwise, also load them but with the difference that with the `loaded` flag set, we won't reset all routes.
- Loading branch information