Strange Issue w/ incorrect controller invocation for nested routes using the same controller name...

Hi, I've been battling a very strange and irritating bug for a long time now. The issue is the following:

I have namespaced my controllers in routes.rb * map.resources :login, :collection => [:login, :logout] * map.namespace :partner do |p|       p.resources :login, :collection => [:login, :logout]     end

As such, I have two distinct controllers app/controllers/ login_controller and app/controllers/partner/login_controller.

I'm running Apache + Passenger 2.0.3. When apache is freshly restarted, requests to /partner/login invoke the proper controller. However, after some period of time (or some series of actions....whatever it is, I cannot isolate it), the wrong controller will be invoked when requesting /partner/login.

Reaching back into my logs, I see no difference in the logging that rails performed.

*** Log entry before bug starts showing up

Processing LoginController#index (for xx.xx.xx.xx at 2008-11-24 10:33:26) [GET]   Session ID: bb63a070c1fa56a703018fa922359146   Parameters: {"action"=>"index", "controller"=>"partner/login"} Rendering template within layouts/application Rendering partner/login/index Completed in 0.00188 (531 reqs/sec) | Rendering: 0.00178 (94%) | DB: 0.00180 (95%) | 200 OK [https://myapp/partner/login\]

*** Log entry after bug has started showing up

Processing LoginController#index (for xx.xx.xx.xx at 2008-11-24 12:26:35) [GET]   Session ID: 5bdeff99bd72fe94cb8b80fd9b6beff6   Parameters: {"action"=>"index", "controller"=>"partner/login"} Rendering template within layouts/static_dashboard Rendering login/index Completed in 0.00286 (349 reqs/sec) | Rendering: 0.00274 (95%) | DB: 0.00429 (150%) | 200 OK [https://myapp/partner/login\]

What kills me is that in parameters, the proper controller/action are being identified. But if you look at the succeeding lines, you'll see different templates being rendered.

This has been happening to me for quite a while. Even prior to moving to Passenger quite a while ago, I saw this same bug crop up in production when using a mongrel_cluster solution behind Pound. So I'm fairly certain that it's not related to Passenger. I have not seen it arise in my local dev environment (running mongrel).

I realize this is quite the shot in the dark, but I was curious if anyone had any thoughts whatsoever on the source of this problem, or if you've encountered anything similar in the past.

Thanks for any help.

-John

Also, worth noting that the app is running rails 2.1.0 currently. I also had this problem when it was previously running 2.0.2. Upgrading to 2.1.2 is potentially an option, but I'm wary of just trying something like that in production when I don't fully understand what the problem is, so I'm holding off on that in the meantime.

-John

Also, worth noting that the app is running rails 2.1.0 currently. I also had this problem when it was previously running 2.0.2. Upgrading to 2.1.2 is potentially an option, but I'm wary of just trying something like that in production when I don't fully understand what the problem is, so I'm holding off on that in the meantime.

Are the classes both named LoginController or is one of them
Partner::LoginController ?

Fred

One is defined like:

class Partner::LoginController < ApplicationController

end

The other is defined like:

class LoginController < ApplicationController

end

Wonder if wrapping the other in module Partner instead of prefixing the classname with the module would have any effect...

-John

One is defined like:

class Partner::LoginController < ApplicationController

end

The other is defined like:

class LoginController < ApplicationController

end

Wonder if wrapping the other in module Partner instead of prefixing the classname with the module would have any effect...

I suspect the complexities of how automatic constant loading work
means that if Partner::LoginController isn't loaded but
LoginController is then it would find the wrong one. using
require_dependency (eg in application.rb) in forcing rails to load
both controllers might help.

Fred

So, to be clear, you're suggesting that I place the following at the top of my application.rb file?

class ApplicationController < ActionController::Base   require_dependency 'partner/login_controller'   require_dependency 'login_controller'

  # ...

end

Should those calls be inside or outside of the ApplicationController? Also, are the paths correct, or should I fully prefix them with RAILS_ROOT?

I've never directly invoked require_dependency before....for what purposes do you find it useful (aside from a potential solution to my struggles)?

Thanks so much!

-John

So, to be clear, you're suggesting that I place the following at the top of my application.rb file?

class ApplicationController < ActionController::Base require_dependency 'partner/login_controller' require_dependency 'login_controller'

# ...

end

Should those calls be inside or outside of the ApplicationController? Also, are the paths correct, or should I fully prefix them with RAILS_ROOT?

Outside the class and you don't need a path or anything

I've never directly invoked require_dependency before....for what purposes do you find it useful (aside from a potential solution to my struggles)?

It's like require but plays nicely with the dependencies system. Use
it whenever you're requiring something that could be magically loaded
(models, controllers etc)

Hey Frederick,

When I place the require_dependency statements above my ApplicationController reference, the initial start of the server blows up. This sort of makes sense to me, because as application.rb is loaded, it will encounter the require_dependency lines first, which I believe will try to load those other controllers. Since, at this point in time, ApplicationController is undefined, LoginController and Partner::LoginController will both fail because ApplicationController (their base class) has yet to be defined.

Make sense?

Should I put these require_dep lines beneath it? This seems to do the trick (at least in the short-term).

For your (and everyone else's) edification, I think this is going to work. I noticed, as I've been working with this on a staging server today, that the bug seemed to crop up when I re-deployed. In other words, fresh deploy (w/ clean apache restart), we're in good shape. Successive deploy (with app restart via touch tmp/restart.txt), we see the error. So perhaps it is a passenger-related bug (although I can definitely recall this happening with a mongrel_cluster solution in the past as well).

Well I chucked those two require_dependency lines at the bottom of application.rb, redeployed (without restarting apache), and voila, the partner/login page was now loading properly (after failing prior to the redeployment). So I have my fingers crossed that I haven't merely been tricked (or rather convinced myself this is the solution) in the interim.

Thanks for the guidance Frederick!

-John

Yeah beneath would be better. You just need to ensure they're loaded
early enough