0

I'm building an application that has a mountable but not isolated rails engine located at APP/sites/my_engine/. My understanding of a typical request with this setup looks like this:

  1. A request goes through the Main App's middleware stack.
  2. The request hit's the Main App's router, and matches the mounted path. It places the mounted part in: env["SCRIPT_NAME"] and sends the request on through the Engine.
  3. The request goes through the Engine's middleware stack.
  4. The request hit's the Engine's router and matches the remaining portion of the route.

Let's say that the route matches in the engine's routes and dispatches to a pages#show action. A controller will be called with the following priority:

  1. If a PagesController exists with the show action in the main app it will call this first.
  2. If a PagesController exists with the show action in the engine it will call this second only if the first did not exist.

If you look at MyEngine::Engine.paths['app/controllers'] it is the default ["app/controllers"]..which in this context is the engine. So why does it find the App's controller first?

Where is this priority of paths for controllers controlled?

4

1 回答 1

0

Ok so this took some time to figure out. What happens when you boot rails in production mode is that towards the end of initialization rails runs (see Initialization Order):

Rails::Engine#eager_load! 

Here Rails grabs all the eager_load_paths, through:

config.eager_load_paths

for example:

[
  APP/controllers/pages_controller.rb, 
  APP/sites/my_engine/controllers/pages_controller.rb
]

For each eager_load_path it calls a method

ActiveSupport::Dependencies#require_dependency. 

In require_dependency, rails calls:

Dependencies#depend_on

which strips each path to just the ending (i.e. "pages_controller") and calls:

Dependencies#search_for_file

This adds back on the .rb so you have "pages_controller.rb" and looks for the file in autoload_paths. Since the Rails paths are first in autoload_paths, Rails will find the App version of the file before it finds the engine version and loads it every time if they share the same name. The rails engine version never gets loaded.

于 2013-03-31T04:05:59.873 回答