Reputation: 43825
I'm trying to setup Subdomains in Rails 3 per Ryan Bates screencast on subdomains. However it's not working for me. I have the following setup:
# routes.rb
constraints(Subdomain) do
get 'devices' => 'devices#all'
end
# lib/subdomain.rb
class Subdomain
def self.matches?(request)
# binding.pry
request.subdomain.present? && request.subdomain == "admin"
end
end
Loading the url admin.localhost:3000/devices
should route me to devices#all
, however I get a routing error Routing Error No route matches [GET] "/devices"
Clearly my routing isn't working.
I setup a pry
debug session where the comment is above, and it gets hit, so my constraint is working, but I get the following output:
[1] pry(Subdomain)> request.subdomain
=> ""
[2] pry(Subdomain)> request.subdomains
=> []
[3] pry(Subdomain)> request.host
=> "admin.localhost"
So rails isn't picking up the admin portion of the url and placing it into the subdomain variable. While I could easily just use the host value to filter to the admin routes, I'd like to keep things clean and correct.
How come rails isn't setting the subdomain value?
Edit
Both jdoe and coreyward are correct with their answers. What was throwing me off was that I was also using pow
and xip.io
to access the site and getting the same error. Which was odd because http://admin.app_name.192.168.1.68.xip.io/devices
has a tld > 1. What was happening was that the subdomain for xip
was admin.app_name.192.168.1.68
, which also fails given the matches logic and doesn't route.
Upvotes: 6
Views: 5172
Reputation: 80041
Because there isn't a subdomain as far as Rails considers it.
Rails expects you to provide a Top-Level Domain (TLD) length for TLDs with more than 1 dot. For example, if you had bbc.co.uk
it would pickup "bbc" as the subdomain unless you specified the TLD length is 2, in which case the subdomain would be blank:
request.subdomain(2) #=> ""
This is also why you're seeing subdomains
return an empty array: the last two segments are being discarded automatically. You could specify 0
as the TLD length to get back "admin", but that code will break in production with a real domain name, so I don't recommend it.
I recommend using a domain like admin.yourapp.dev that is routed back to your computer via localhost to make your app properly detect a subdomain. Just edit /etc/hosts to do it simply.
If you're curious, here is the Rails source for the subdomain
method.
Upvotes: 12
Reputation: 15771
Try using special address: http://admin.lvh.me:3000/devices
Or set:
config.action_dispatch.tld_length = 0
in your development.rb and restart your app.
Upvotes: 7