Recently I was working on using subdomains in a Rails app. Basically, I needed to be able to look up a database record based on the subdomain, so I needed to be able to access the subdomain in my controller.

Domains and subdomains are one of those things where it’s not immediately obvious how to test in development, since you can’t just visit http://sub.localhost:3000 and have it work without doing a little setup.

It took some searching to find all the info I needed, scattered across a few Stack Overflow questions and blog posts, so I’m posting it here to have everything in one place.

Plan A: lvh.me

In the past, I’ve used lvh.me, a domain that’s pointed at localhost. If you have a local server running on port 3000, http://lvh.me:3000 will get your server. It has a wildcard DNS record, so [anything].lvh.me will point to localhost. Here’s some more info about lvh.me.

This worked beautifully before, but unfortunately, for some reason I couldn’t get it to work in the office this time. At home, it loads fine, so either I was making a stupid mistake, it was down temporarily, or some firewall was blocking it. Anyway, here’s what I ended up doing instead:

Plan B: editing the hosts file

First, I added sub.localhost to my hosts file following the instructions in this blog post.

In my Rails controller, I attempted to call request.subdomain to get the subdomain, but it was returning an empty string, while request.domain was returning 'sub.localhost'.

From this Stack Overflow answer I learned that I needed to add config.action_dispatch.tld_length = 0 to config/environments/development.rb. Now, request.subdomain returns 'sub' and request.domain returns 'localhost'.

That answer linked to this comment on a GitHub issue which explains that tld_length refers to the number of dot-separated pieces of the TLD. The default is 1, for TLDs like .com. It would need to be 2 for TLDs like .co.uk.

Subdomains in tests

Finally, in my Capybara tests, I used Capybara.app_host = "http://sub.mydomain.com" to fake the subdomain, as explained in another Stack Overflow post.