好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

rails3已经内置subdomain

rails3已经内置subdomain

Brian Cardarella's Blog Home Archive RSS Mobile About Brian

19 June 2010

3 notes

Rails 3 subdomains Router

Custom Subdomains in Rails 3

Rails 3 supports subdomains out of the box , which is great. But did you know that the constraints in the Router can actually match patterns too? This means instead of hardcoding each subdomain into your routes you can allow your customers to decide their own subdomains.

However, we have to be careful with pattern matching on the subdomain. There are obvious subdomains we don’t want to match. Like ‘www’, ”, nil, and others that we may reserve. In this case using a pattern match might not be best.

Thankfully the Rails 3 Router constraints can also take objects. As long as the object responds to Object.matches?. The request is passed to the method and you can act on it in any way. The following is the solution that I’ve found works for me.

I created a ‘lib/sub_domain.rb’ with the following code:

 # lib/sub_domain.rb
class SubDomain
  def self.matches?(request)
    case request.subdomain
    when 'www', '', nil
      false
    else
      true
    end
  end
end
 

In my routes.rb file I can now wrap all routes I want under a custom subdomain

 # config/routes.rb
TestApp::Application.routes.draw do |map|
  constraints(SubDomain) do
    root :to => "customers#index"
  end
  
  root :to => "home#index"
end
 

Finally, I create a SubDomainController from which all controllers under the subdomain constraint can inherit from

 # app/controllers/sub_domain_controller.rb
class SubDomainController < ApplicationController
  before_filter :get_customer_from_subdomain
  
  private
  
  def get_customer_from_subdomain
    @customer = Customer.find_by_subdomain!(request.subdomain)
  end
end
 
 # app/controllers/customers_controller.rb
class CustomersController < SubDomainController
  def index
    ...
  end
end
 

Having the SubDomainController is a nice way for me to encapsulate behavior that I want every subdomain to have. One such idea would be customer specific layouts. (or themes)

Check out Phil McClure’s post on localhost subdomains if you want to use this functionality in your development and test environments .

Update

To link to your dynamic subdomains you can completely overwrite the :host option in the url helper:

 root_url(nil, {:host => "subdomain.somedomain.com"})
 

This is not ideal. It constrains us to this particular domain. What we need is to be able to pass a :subdomain option to the url helper. (btw, you need to use the url helpers for linking to subdomains and not the path helpers)

So I quickly wrote up this code. Just add it to your ApplicationController and it will be available to your entire app:

 class ApplicationController < ActionController::Base
  ...
  private
  
  # To write subdomains on the url helpers:
  # root_url(nil, {:subdomain => "subdomain"})
  def url_for(options = nil)
    case options
    when Hash
      if subdomain = options.delete(:subdomain)
        if request.subdomain.empty?
          options[:host] = "#{subdomain}.#{request.host_with_port}"
        else
          options[:host] = request.host_with_port.sub(request.subdomain, subdomain)
        end
      end
    end
    super
  end
end
 

So now you can do:

 root_url(nil, {:subdomain => "subdomain"})
 

Notes maxschulze liked this apeacox liked this jackhq reblogged this from bcardarella bcardarella posted this

Like Dislike

4 people liked this. Community

Disqus

Glad you liked it. Would you like to share?

Facebook

Twitter

Share No thanks

Sharing this page ...

Thanks! Close

Add New Comment

  阅读:38次