Engine's Application Controller

Hi,

I've been using rails 3 engines and (at least in my experience) the engine's application controller is overidden by the app's application controller. Wouldn't it be better if the app would just load on top of the engine?

I mean that if an engine's application controller has methods or anything else that does not collide with the stuff defined with the app, couldn't it be used?

Isn't this the default behaviour of ruby, that you can just reopen a class and add methods to it possibly overriding them but not deleting the rest of the class?

Regards,
Luís Ferreira

See previous discussion on this thread:
https://groups.google.com/group/rubyonrails-core/browse_thread/thread/449521aed8b4cd7a#

That thread did result to this change in the guides:
https://github.com/rails/rails/commit/a0d9b7903588cd988c8c9b4164494c792344f43e

Hope that helps.

Mark

Indeed, the application’s app/controllers/application_controller.rb will take precedence over a similarly named file in the engine. The same goes for anything else in the app directory, too.

This is why you namespace your engine: to avoid collisions such as these.

Ok. This will solve the problem, but still I don’t understand why both application controllers could not be merged.

Ok. So now I’ve namespace my ApplicationController like so:

class Citygate::Admin::ApplicationController < ::Admin::ApplicationController

protect_from_forgery

layout ‘admin/application’

rescue_from CanCan::AccessDenied do |exception|

redirect_to root_url, :alert => exception.message

end

end

The problem here is that I want the app/admin/application_controller.rb to be able to change the cancan redirect and since the engine’s controller inherits from it, the engine’s definitions will always take precendence. This is not the functionality I want. I want to be able to provide some defaults in the engine that can be overidden in the app.

Am I doing anything wrong here?

If you just merged the ApplicationControllers, then the code in the last loaded engine would take precedence in the main app and all other engines. And if you overwrote some methods in one engine and others in another you would quickly have a quagmire.

Using inheritance provides a nice predictable way to change behavior. This way you main application stays unaltered and each engine can access this code and change its behavior without affecting the main app or other engines.

Ok. I get it. It would really be a mess when you have multiple engines, I’ll namespace everything in the engine. Thanks.

Still, this won’t solve my cancan problem.

Insert some warning about why it would be better to change the code in your main app here. But, if you want to change it in your engine you can. Something like

class ::Admin::ApplicationController

do your monkey patching here

end

Just make sure this is in a file that gets loaded when your engine loads – I would suggest an initializer, but …

Your monkey patch will allow me to change the app from the engine. But my idea was to change the engine from the app.

Maybe this could be solved some other way, since my problem is as simple as wanting to set some defaults in the engine’s application controller and allowing the app to change those defaults easily (eg. overwriting them in its own application controller).

Is there a better way of doing this?

BTW, the engine’s routes.url_helpers are not loaded in rspec and cucumber tests by default. It feels kind of hackish to load them myself. Wouldn’t it be possible to correct this or is it a feature?