Engine routes in Application Controller

前端 未结 5 2112
予麋鹿
予麋鹿 2020-12-29 10:20

I have a before_filter hook in my main app\'s application controller that does something like: (It doesn\'t just put a link in the flash, there is a message, but it isn\'t r

相关标签:
5条回答
  • 2020-12-29 10:53

    Mountable engines are designed to work like this, that is isolate the main app routes and the engine routes.

    If you want the two sets of routes to be merged, you can use a non-isolated engine. The first step is removing the isolated_namespace method call in your engine definition:

    module MyEngine
      class Engine < Rails::Engine
        isolate_namespace MyEngine # remove this line
      end
    end
    

    The second step is to convert your routes in my_engine/config/routes.rb, you should go from this:

    MyEngine::Engine.routes.draw do
      # stuff that routes things
    end
    

    to this:

    Rails.application.routes.draw do
      # stuff that routes things
    end
    

    and remove the mount method call in your application's routes:

    App::Application.routes.draw do
      mount MyEngine::Engine => "/engine" # remove this line
    end
    

    The main advantages of doing it this way would be:

    1. No need to monkey-patch rails. I know devise does this, but this could be a leftover from the days when engines didn't exist in rails.

    2. No need to mount the engine in the application routes. On the other hand, this could backfire if you'd like to control more precisely the insertion point as all you engine routes would be called after (or before, I don't have the answer to this question) your main routes.

    If you're looking for documentation on engines, the rails docs for the Engine class are a pretty good starting point. I'd strongly recommend that you read them (in case you haven't yet) if you're interested in the subject.

    0 讨论(0)
  • 2020-12-29 10:57

    I figured out how to do this. The problems lies within the isolated namespace. In order to integrate the engine with the app and share the same layout (which may have path helpers from the main app) I did this:

    Firstly I removed config/routes.rb from the engine

    Then I removed the isolate_namespace from the engine class

    module MyEngine
       class Engine < Rails::Engine
    -    isolate_namespace MyEngine
       end
     end
    end
    

    I added a file that was loaded in the engine:

    module ActionDispatch::Routing
      class Mapper
        def mount_my_engine_at(mount_location)
          scope mount_location do
            #Declare all your routes here
          end
        end
      end
    end
    

    Finally, in the main app's config/routes.rb instead of 'mount'ing the engine, you can call your method

    mount_my_engine_at "mount_location"
    

    This will basically 'mount' your engine as part of the main app instead of being isolated from it. It is similar to how Devise does it too.

    0 讨论(0)
  • 2020-12-29 10:59

    You can keep the isolate_namespace. In your engine routes.rb

    MyEngine::Engine.routes.draw do
      ...
      root to: "something#index"
    end
    
    Rails.application.routes.draw do
      get "something", to: "my_engine/something#index"
    end
    

    And then in the main app routes.rb

    Rails.application.routes.draw do
    
      mount MyEngine::Engine => "/anything_you_want"
    
      root to: "main#index"
    end
    

    This way you can choose what routes you want to expose (and which you do not)

    0 讨论(0)
  • 2020-12-29 11:06

    You can keep the isolate_namespace, as strongly recommended by Rails Engine guide, and do this:

    # inside your main_app's config/routes.rb
    Rails.application.routes.draw do
      root to: 'home#index'
    
      mount MyEngine::Engine, at: "/" 
    end
    
    # inside your engine's controller
    module MyEngine
      class SomeController << ::ApplicationController
        # include main_app's route helpers
        helper Rails.application.routes.url_helpers
    
      end
    end
    

    And inside your gem, make sure all the url helpers are prefixed with the correct routing proxy method (e.g. my_engine.pages_path).

    Your main_app's layout and engine's controller will route and link to those url helpers correctly to the main app. You don't have to add "main_app" prefix anywhere to the main app. The only downside is you're mounting your engine's routes at main_app's root path, which could collide with any routes by the same name. This is expected anyway if you were to do non-isolate_namespace.

    0 讨论(0)
  • 2020-12-29 11:08

    The easiest way is to draw the routes in both the main app, and the engine, so that they are accessible to both:

    [MyEngine::Engine, App::Application].each do |app|
      app.routes.draw do
        # Declare all your routes here
      end
    end
    
    0 讨论(0)
提交回复
热议问题