Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails Restful Routing and Subdomains

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.

like image 541
mark Avatar asked Sep 07 '10 07:09

mark


People also ask

What are RESTful routes in Rails?

In Rails, a RESTful route provides a mapping between HTTP verbs, controller actions, and (implicitly) CRUD operations in a database. A single entry in the routing file, such as. map.resources :photos. creates seven different routes in your application: HTTP verb.

What is the difference between resources and resource in Rails?

Difference between singular resource and resources in Rails routes. So far, we have been using resources to declare a resource. Rails also lets us declare a singular version of it using resource. Rails recommends us to use singular resource when we do not have an identifier.

How do I see all routes in Rails?

TIP: If you ever want to list all the routes of your application you can use rails routes on your terminal and if you want to list routes of a specific resource, you can use rails routes | grep hotel . This will list all the routes of Hotel.


2 Answers

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
like image 81
Igor Alexandrov Avatar answered Oct 20 '22 16:10

Igor Alexandrov


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
like image 35
Nader Avatar answered Oct 20 '22 15:10

Nader