views:

271

answers:

3

Hi

I wondered if there were any plugins or methods which allow me to convert resource routes which allow me to place the controller name as a subdomain.

Examples:

map.resources :users
map.resource :account
map.resources :blog
...

example.com/users/mark
example.com/account
example.com/blog/subject
example.com/blog/subject/edit
...

#becomes

users.example.com/mark
account.example.com
blog.example.com/subject
blog.example.com/subject/edit
...

I realise I can do this with named routes but wondered if there were some way to keep my currently succinct routes.rb file.

+4  A: 

Hello Mark.

I think that subdomain-fu plugin is exacly what you need. With it you will be able to generate routes like

map.resources :universities,
    :controller => 'education_universities',
    :only => [:index, :show],
    :collection => {
        :all    => :get,
        :search => :post
    },
    :conditions => {:subdomain => 'education'}

This will generate the following:

education.<your_site>.<your_domain>/universities GET
education.<your_site>.<your_domain>/universities/:id GET
education.<your_site>.<your_domain>/universities/all GET
education.<your_site>.<your_domain>/universities/search POST
Igor Alexandrov
Hi Igor and thanks for your reply. I have looked at subdomainfu but the problem is it effectively adds a namespace as the subdomain name, rather than using the controller name which is what I was hoping for. In your example I would wish to drop education and move universities (the controller name) to be the subdomain.
mark
Hello Mark, now I have the same issue and that is what I've done. I created namespace Education, with parameters :name_prefix => '' and :path_prefix => ''. In this namespace you can do whatever you want, I have several additional namespaces inside it. But for each route inside it, you should add :conditions => {:subdomain => 'education'}. I don't know, how to write better about it, but I think that it works well. If you want, contact me, and I will show you.
Igor Alexandrov
+2  A: 

The best way to do it is to write a simple rack middleware library that rewrites the request headers so that your rails app gets the url you expect but from the user's point of view the url doesn't change. This way you don't have to make any changes to your rails app (or the routes file)

For example the rack lib would rewrite: users.example.com => example.com/users

This gem should do exactly that for you: http://github.com/jtrupiano/rack-rewrite

UPDATED WITH CODE EXAMPLE

Note: this is quickly written, totally untested, but should set you on the right path. Also, I haven't checked out the rack-rewrite gem, which might make this even simpler

# your rack middleware lib.  stick this in you lib dir
class RewriteSubdomainToPath

  def initialize(app)
    @app = app
  end

  def call(env)
    original_host = env['SERVER_NAME']
    subdomain = get_subdomain(original_host)
    if subdomain
      new_host = get_domain(original_host)
      env['PATH_INFO'] = [subdomain, env['PATH_INFO']].join('/')
      env['HTTP_X_FORWARDED_HOST'] = [original_host, new_host].join(', ')
      logger.info("Reroute: mapped #{original_host} => #{new_host}") if defined?(Rails.logger)
    end

    @app.call(env)

  end

  def get_subdomain
    # code to find a subdomain.  simple regex is probably find, but you might need to handle 
    # different TLD lengths for example .co.uk
    # google this, there are lots of examples

  end

  def get_domain
    # get the domain without the subdomain. same comments as above
  end
end

# then in an initializer
Rails.application.config.middleware.use RewriteSubdomainToPath
Nader
This makes the most sense to me, since the emphasis is on being restful. If you can elaborate a bit more, maybe with a code example, I'll give you the bounty. Would this method have any potential problems with cookies?
Jeriko
Updated with a code example. Cookies should be fine as all requests will be coming to the same base domain as far as your rails app is concerned. Unless you are trying to maintain different sets of cookies for each user.
Nader
Damn - it seems the bounty expired before I could award it to you. Not sure if it's completely lost or if there's anything I can do to recover it, will find out..
Jeriko
Guess that didn't work out?
Nader
A: 

Ryan Bates covers this in his Railscast, Subdomains.

Yasky
Sorry Yasky, the Railscast doesn't really address restful subdomains specifically, and it ends up being a bit vague. Not my -1, though.
Jeriko