An example Rails 3 app with basecamp like subdomains and authentication (using Devise).
Ruby JavaScript
Switch branches/tags
Nothing to show
Clone or download
Pull request Compare This branch is 10 commits ahead, 30 commits behind fortuity:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


Fork of Rails3-Subdomain-Devise modified for basecamp-like subdomaims


This was the initial version of implementing subdomains using a BaseCamp like approach. While it is functional, I really didn’t get everything quite right. Quite right is really up to your application. I have posted another repository that cleans up a few thing and adds Devise Invitable to implement invitations and CanCan to do some basic authorization. Pick your poison! rails3-Devise-BCSD-Can-Invite.

Use this project as a starting point for a Rails 3 application that uses basecamp-like subdomains and authentication. User management and authentication is implemented using Devise.

This is a stab of modifying Rails3-Subdomain-Devise to provide basecamp-like subdomains.

Thanks to babinho’s fork for cleaning up some things up and going back to a subdomain id instead of name as the primary key.

The major changes are:


Routes and associations were modified:

  devise_for :users
  resources :users, :only => [:index, :show]   do
    member do
      get :valid
  resources :subdomains, :only => [:index, :show]
  constraints(SubdomainRoute) do
    match '/' => 'sites#index'
    match '/opps' => 'sites#opps'
  root :to => "home#index"

User and subdomains are no longer nested, but associated.

	class Subdomain < ActiveRecord::Base
	  has_many :users
	  validates_uniqueness_of :name, :case_sensitive => false
	  validates_presence_of :name
	class User < ActiveRecord::Base
	  belongs_to :subdomain
	  devise :database_authenticatable, :registerable,
	         :recoverable, :rememberable, :trackable, :validatable
	  validates_presence_of :name
	  validates_presence_of :subdomain_name, :on => :create # used to create a subdomain
	  validates_uniqueness_of  :email, :case_sensitive => false
	  attr_accessor :subdomain_name  # used to create a subdomain
	  attr_accessible :name, :subdomain_name, :email, :password, :password_confirmation, :loginable_token
	  before_create :create_subdomain
	  after_create :update_subdomain_owner

	  def self.valid?(params)
	    token_user = self.where(:loginable_token => params[:id]).first
	    if token_user
	      token_user.loginable_token = nil
	    return token_user


	  def create_subdomain
	    # get or create a subdomain on creating a new user
	    self.subdomain = Subdomain.find_by_name(self.subdomain_name) 
	    self.subdomain ||= Subdomain.create!(:name => self.subdomain_name)

	  def update_subdomain_owner
	    # set owner of subdomain to user that created it
	    subdomain = self.subdomain
	    if subdomain && subdomain.user_id.nil?
	      subdomain.user_id =


The majority of the subdomains controller has been stubbed in that “sign_up” will create a subdomain if it does not exist. Code was not removed in that an Admin user might want to delete subdomains and associated users.

The model names were not changed, but take on different roles. List of other changes:

  • Users#index probably should not be there, but it lists all users
  • Site would be the home for the site and currently list users for the subdomain
  • Subdomain still has user_id and indicates who created the subdomain (assume subdomain admin)
  • A helper method “current_subdomain” was added to controllers/application.rb to check if subdomain exists
  • Another helper method “check_my_domain(subdomain)” will check a passed subdomain against the current domain. Subdomain is kind of the root table, all major tables should be belong to subdomain and this check is there to prevent url modification (edit member not belonging to your domain). It will redirect to an “opps” action in the site controller.
  • Sign-in has been removed if no subdomain exists. If you modifiy the url and sign_in without a subdomain. It will log you in, but then immediately log you out and redirect to the subdomain sign_in form. I can’t seem to get the flash notice to work in this area.
  • If you sign-in to the root domain.
    • A token is saved in the users record. You are signed_out of the root domain and redirected a user/valid action in the subdomin.
    • The valid action will check the token and if found, will clear the toke and sign-in the user to the subdomain.
  • If you register without a subdomain, it will be created when the user is created. If it exists, you are added as a user of that subdomain (TODO this should be fixed to reject adding user from sign_up without subdomain, if it exists)
  • If you register in a subdomain, you are added as a the users of that subdomain.

P.S. I am not a novice at Rails, but don’t consider myself experienced.


  • git clone
  • bundle install
  • rake db:create
  • rake db:migrate
  • rake db:seed


Please visit Rails3-Subdomain-Devise for the excellent step-by-step tutorial. You should still be able to follow the tutorial for this fork if you address the above changes.


Version (fork) that uses Mongodb with Mongoid by millisami at


Public Domain Dedication

This work is a compilation and derivation from other previously released works. With the exception of various included works, which may be restricted by other licenses, the author or authors of this code dedicate any and all copyright interest in this code to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this code under copyright law.