Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails routing to handle multiple domains on single application

I've been unable to find a workable solution to this problem, despite several similar questions here and elsewhere. It seems likely that this question hasn't been answered for Rails 3, so here goes:

I have an application that currently allows users to create their own subdomain that contains their instance of the application. While in Rails 2 you were best served using the subdomain-fu gem, in version 3 it's dramatically simpler, as per the Railscast -- http://railscasts.com/episodes/221-subdomains-in-rails-3.

That's good stuff, but I also want to provide the option for users to associate their own domain name with their account. So while they might have http://userx.mydomain.com, I'd like them to choose to have http://userx.com associated as well.

I found a few references to doing this in Rails 2, but those techniques don't appear to work anymore (particularly this one: https://feefighters.com/blog/hosting-multiple-domains-from-a-single-rails-app/).

Can anyone recommend a way to use routes to accept an arbitrary domain and pass it along to a controller so I can show the appropriate content?

Update: I've gotten most of an answer now, thanks to Leonid's timely response, and a fresh look at the code. It ultimately required an addition to the existing Subdomain code that I was using (from the Railscast solution) and then adding a bit to routes.rb. I'm not all the way there yet but I want to post what I have so far.

In lib/subdomain.rb:

class Subdomain   def self.matches?(request)     request.subdomain.present? && request.subdomain != "www"   end end  class Domain   def self.matches?(request)     request.domain.present? && request.domain != "mydomain.com"   end end 

I've added the second class in imitation of the first, which is known working. I simply add a condition that ensures that the incoming domain is not the one for which I'm hosting the main site.

This class is used in routes.rb:

require 'subdomain' constraints(Domain) do   match '/' => 'blogs#show' end  constraints(Subdomain) do   match '/' => 'blogs#show' end 

Here, I'm prepending the existing subdomain code (again, it's working fine) with a stanza to check for the Domain. If this server responds to that domain and it's not the one under which the main site operates, forward to the specified controller.

And while that appears to be working, I don't quite have the whole thing working yet, but I think this particular problem has been solved.

like image 588
Aaron Vegh Avatar asked Nov 17 '10 18:11

Aaron Vegh


People also ask

What is namespace routes in Rails?

This is the simple option. When you use namespace , it will prefix the URL path for the specified resources, and try to locate the controller under a module named in the same manner as the namespace.

How many types of routes are there in Rails?

Rails RESTful Design which creates seven routes all mapping to the user controller. Rails also allows you to define multiple resources in one line.

What is Tld_length?

The tld_length parameter is used in splitting HOST into domain and subdomain components. Unfortunately, @@tld_length is used in other functions, so to be thread safe you would have to find and rewrite all those functions as well as provide thread-local storage.

What is Route helper in Rails?

Running route helpers in the rails console is a great way of testing out routes to see what their exact output will be. Column 4 - This column shows the controller and action with a syntax of controller#action.


2 Answers

It's actually simpler in Rails 3, as per http://guides.rubyonrails.org/routing.html#advanced-constraints:

1) define a custom constraint class in lib/domain_constraint.rb:

class DomainConstraint   def initialize(domain)     @domains = [domain].flatten   end    def matches?(request)     @domains.include? request.domain   end end 

2) use the class in your routes with the new block syntax

constraints DomainConstraint.new('mydomain.com') do   root :to => 'mydomain#index' end  root :to => 'main#index' 

or the old-fashioned option syntax

root :to => 'mydomain#index', :constraints => DomainConstraint.new('mydomain.com') 
like image 61
Leonid Shevtsov Avatar answered Sep 19 '22 15:09

Leonid Shevtsov


In Rails 5, you can simply do this in your routes:

constraints subdomain: 'blogs' do   match '/' => 'blogs#show' end 
like image 23
user3033467 Avatar answered Sep 17 '22 15:09

user3033467