Skip to content

Instantly share code, notes, and snippets.

@jtanium
Last active August 25, 2020 09:28
Show Gist options
  • Save jtanium/6114632 to your computer and use it in GitHub Desktop.
Save jtanium/6114632 to your computer and use it in GitHub Desktop.
Ruby module that can recognize paths of the main Rails application as well as the engines.
module RecognizePath
def recognize_path(path, options)
recognized_path = Rails.application.routes.recognize_path(path, options)
# We have a route that catches everything and sends it to 'errors#not_found', you might
# need to rescue ActionController::RoutingError
return recognized_path unless recognized_path.slice(:controller, :action) == {controller: 'errors', action: 'not_found'}
# The main app didn't recognize the path, try the engines...
Rails.application.railties.engines.each do |engine|
# Find the route to the engine, e.g. '/blog' -> Blog::Engine (a.k.a. "mount")
engine_route = Rails.application.routes.routes.find { |r| r.app.to_s == engine.class.to_s }
next unless engine_route
# The engine won't recognize the "mount", so strip it off the path,
# e.g. '/blog/posts/new'.gsub(%r(^/blog), '') #=> '/posts/new', which will be recognized by the engine
path_for_engine = path.gsub(%r(^#{engine_route.path.spec.to_s}), '')
begin
recognized_path = engine.routes.recognize_path(path_for_engine, options)
rescue ActionController::RoutingError => e
Rails.logger.debug "[#{engine}] ActionController::RoutingError: #{e.message}"
end
end
recognized_path
end
end
@nmeylan
Copy link

nmeylan commented Oct 30, 2014

For rails 4.1

see : rails/rails@4a2a504#diff-7d0a784885a7ba0f99b77cb306dba31b to know the reason.

def recognize_path(path, options)
          recognized_path = Rails.application.routes.recognize_path(path, options)
          # We have a route that catches everything and sends it to 'errors#not_found', you might
          # need to rescue ActionController::RoutingError
        rescue ActionController::RoutingError
          # The main app didn't recognize the path, try the engines...
          Rails::Engine.subclasses.each do |engine|
            engine_instance = engine.instance
            # Find the route to the engine, e.g. '/blog' -> Blog::Engine (a.k.a. "mount")
            engine_class = engine_instance.class
            engine_route = Rails.application.routes.routes.find { |r| r.app == engine_class }
            next unless engine_route

            # The engine won't recognize the "mount", so strip it off the path,
            # e.g. '/blog/posts/new'.gsub(%r(^/blog), '') #=> '/posts/new', which will be recognized by the engine
            path_for_engine = path.gsub(%r(^#{engine_route.path.spec.to_s}), '')
            begin
              recognized_path = engine_instance.routes.recognize_path(path_for_engine, options)
            rescue ActionController::RoutingError => e
              Rails.logger.debug "[#{engine}] ActionController::RoutingError: #{e.message}"
            end
          end

          recognized_path
        end

@dtelaroli
Copy link

r.app == engine_class
never is equals

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment