If you are using the
routing-filter
Show archive.org snapshot
gem in your Rails 7.1 app for managing URL segments for locales or suffixes, you will notice that the filters do no longer apply, routes are broken and the necessary parameters are no longer extracted. That is because routing-filter patches Rails' find_routes
-method to get the current path and apply its defined filters on it. These filters then modify the params that are handed over to your controller action. This way you receive a locale
parameter from a matching URL segment.
Before Rails 7.1, this method returned all associated routes (as enumerable) and the using methods iterated over them. As the using methods like serve
do not actually need all routes, but may return early,
a change
Show archive.org snapshot
has been introduced to add lazy behavior by adding an iterator block and yielding. This change breaks the adapter patch in routing-filter as it still expects an array of route data when calling super
, but never actually calls the block that now needs to be called. Due to this, the return value is empty, no filters are applied and the routes go missing.
To fix this, you need to monkeypatch the patch/adapter in routing-filter until a new version may eventually come out. There is already an open PR Show archive.org snapshot .
In your app, create a file lib/ext/routing_filter/adapters/routers/journey.rb
and add the following content:
if Gem.loaded_specs['routing-filter'].version > Gem::Version.new('0.7')
raise 'Check if PR https://github.com/svenfuchs/routing-filter/pull/87 has been merged and released. If yes, delete this monkey patch.'
end
# We cannot prepend a custom extension module here because we call `super` in this method which should call the Rails
# #find_routes-method and not the routing_filter's #find_routes-method which is broken.
# Instead, we override the whole module definition to fix it.
module ActionDispatchJourneyRouterWithFiltering
def find_routes(env)
path = env.is_a?(Hash) ? env['PATH_INFO'] : env.path_info
filter_parameters = {}
original_path = path.dup
@routes.filters.run(:around_recognize, path, env) do
filter_parameters
end
super(env) do |match, parameters, route|
parameters = parameters.merge(filter_parameters)
if env.is_a?(Hash)
env['PATH_INFO'] = original_path
else
env.path_info = original_path
end
yield [match, parameters, route]
end
end
end
Add an initializer config/initializers/ext.rb
, if not yet present:
Dir.glob(Rails.root.join('lib/ext/**/*.rb')).sort.each do |filename|
require filename
end
Restart your application. The routing should now work again.