Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
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 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
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