How to use Webrat AND Mongrel with a prefix/subdomain

There’s a long-standing bug in the Mongrel webserver that means that the prefix option (needed to host your app in a subdomain) is broken. The problem is that it’s referring to a method in a deprecated class (ActionController::AbstractRequest), and the traditional way to solve this problem is to add the missing method back in and “re-route” it to the new version, using something like this:

module ActionController
    class AbstractRequest < ActionController::Request
        def self.relative_url_root=(path)
            ActionController::Base.relative_url_root=(path)
        end

        def self.relative_url_root
            ActionController::Base.relative_url_root
        end
    end
end

(This is taken from one of the bug reports for this on the mongrel website).

There’s a big problem with this though – it’s fairly common for gems to look for the presence of ActionController::AbstractRequest to determine which version of ActionController is being used (two examples that I’ve noticed in my current project are will_paginate and webrat). So by defining this you could run into problems later on (personally I hit this only when I started using Cucumber, which I’m using with webrat).

The first thing that I tried to get around this was to set config.action_controller.relative_url in environment.rb, as this seems to be the currently recommended way of setting the url root (this is what Mongrel is trying to do in the first place). However, after setting this variable Mongrel was still not using the prefix correctly (various things weren’t loading at the correct prefix), regardless of whether I set the –prefix option for Mongrel on the command line or not.

Finally I came to the conclusion that the only way to fix it was to actually edit the code of my Mongrel install. I’m not sure I can recommend this but it works, and in many ways it’s more “correct” than other methods that I’ve read.

Solution

Find your out where your Mongrel gem is installed (on unix-like systems this is probably /usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5) and open lib/mongrel/rails.rb. The offending line is line 151:

ActionController::AbstractRequest.relative_url_root = ops[:prefix] if ops[:prefix]

Change this to:

if ops[:prefix]
    if ActionController::Base.respond_to?('relative_url_root=')
        ActionController::Base.relative_url_root = ops[:prefix]
    else
        ActionController::AbstractRequest.relative_url_root = ops[:prefix]
    end
end

This is taken from another bug report for this problem on the mongrel website.

Advertisements

About this entry