Monday, January 11, 2010

Rails : Passenger Is Deleting my Sub / RailsBaseURI Prefix

Ok, this was a weird one.  I’m not going to jump into a lesson in how to make Phusion Passenger work to deploy Rails applications, but suffice to say that I had a situation working where we have multiple controller entry points all in to the same application, so I had this:

RailsBaseURI   /foo
RailsBaseURI  /bar

/foo and /bar, then, are soft links from the docroot over to the Rails application’s public folder.  The dispatcher is smart enough to say “Ok, based on the public folder I know where the Rails app lives, and once I know that I can go invoke the appropriate controller.”  So a request for /foo would expect there to be a foo_controller.rb file.

That’s been working fine for me in production for months.

But this week I got the most annoying problem – I added /baz, and kept everything else the same – the soft link, the RailsBaseURI, the baz_controller file.  But now all of a sudden I’m getting  :

No route matches "" with {:method=>:get}

And, let me tell you, it is very hard to Google for empty strings.  I got plenty of examples of people having trouble with No route matches “/foo” or “/approot”, but in each case it was at least telling them their route – mine was being eaten!

On a hunch I would try /baz/baz – and it worked fine.  I tried /baz/ (note the trailing slash) and suddenly my “No route matches” error would turn into “/”.  Aha, I had it – somehow my prefix, which I’m relying on to handoff to my controller, is being eaten.  So by the time Passenger spots “/baz” and hands off to Rails, it just gives “” – and Rails in this case doesn’t know what to do with “” because I don’t have a default route set up.

The problem appears related to an update to Rails, in conjunction with Passenger.  Many people pointed me to this fix:

config.action_controller.relative_url_root=”/baz”

I dismissed this out of hand, though, because of my multiple controllers.  What value would I put in there?  I did not want my app to default to one particular entry point.

Turns out I dismissed it too soon.  What I did was add this:

config.action_controller.relative_url_root=’’

And guess what?  Success!  The best way I can take to interpret this is that it’s telling Phusion “Hey, the value in this variable?  I need this, don’t kill it.”  For instance when I made it a “/” value I suddenly started getting errors saying that I had no “baz” route (see how no slash?)  So by saying that I have no relative url root, I’m saying “It’s not safe to delete anything that came in as if it were extra baggage, just leave it all in place please.”

That may be a painful explanation, particularly to anybody who understands the guts of the Passenger/Rails handoff, but it’s working for me now and I’m abiding by my “If I couldn’t find the answer by googling that means other people have the same problem” rule and posting for the next guy.

No comments: