NoMethodError

raise "a blog about rails, javascript, and other stuff"

Using Wildcard Domains With Rails

Working on a recent project, I needed to allow users to set custom domains to point to their account pages on my server. They would set their domain when they registered, then set an A Record with their DNS to point to my server. The only problem was, I didn’t know how to get Rails to do this.

The domain is already saved in the database, but I needed to tell the router to look for any incoming requests to a domain that doesn’t match my primary domain (in this example, we’ll say my primary domain is example.com). Thanks to Rails 3, I could just add a routing constraint (which can take a class as argument), like so

Notice that the root path is below the domain routes. This is important because it will get triggered before the domain routes otherwise (because routes are first come, first served). With these routes in place, it’s as easy as finding the user by domain when we get a request.

We added the Domain class as a constraints argument, now we need to add that file. You can add the following domain.rb to your lib folder and make sure it’s getting loaded on application boot.

It’s as easy as that. We just check to make sure the domain is present and that it doesn’t match our primary domain. This constraint will match any domain other than our primary domain.

As for server configuration, you have to tell your server to accept all incoming requests, regardless of domain. Below is a sample Apache virtualhost to accomplish this. Notice that we don’t specify a ServerName or ServerAlias, we want it to match everything.

IMPORTANT: You need to ensure that this virtualhost entry is loaded last. If you have any other virtualhosts that specify a ServerName, then they need to be loaded before this one. We’re using this entry as a catch-all to route to our rails app. If you have all of your virtualhosts in one file, just put this entry last. If each entry is in its own file, just make sure this file is loaded last (you might add a zzz_ to the start of the filename to make sure).

Comments