Have Devise create a subdomain on registration

devise, ruby, ruby-on-rails, subdomain

Solution

One subdomain per user is a fairly common use-case in web application development. Here's how you can do it:

First: ensure your `Users table` has a `:name column` (I think Devise does this by default - if not you can run `rails g migration AddNameToUsers name:string` to add this column to your database).

To use this `User.name` as a subdomain we’ll need to make sure it only contains alphanumeric characters (with an optional underscore). We’ll also limit the name to a maximum of 32 characters. Finally, we don’t want users to choose names such as “www” that will result in URLs such as “http://www.myapp.com”. Here's the validations for `app/models/user.rb`:

validates_format_of :name, with: /^[a-z0-9_]+$/, 
  message: "must be lowercase alphanumerics only"

validates_length_of :name, maximum: 32, 
  message: "exceeds maximum of 32 characters"

validates_exclusion_of :name, in: ['www', 'mail', 'ftp'], 
  message: "is not available"

Optionally: modify your db/seeds.rb (so it creates test users when you initialize the database):

user = User.create! :name => 'myname', :email => 'user@example.com', 
  :password => 'password', :password_confirmation => 'password'

We’ll display a profile page for a user when anyone enters a URL with a subdomain that matches an existing user `app/controllers/profiles_controller.rb`:

class ProfilesController < ApplicationController
  def show
    @user = User.where(:name => request.subdomain).first || not_found
  end

  def not_found
    raise ActionController::RoutingError.new('User Not Found')
  end
end

Here's an example file for the view `app/views/profiles/show.html.erb`:

<h1>Profile</h1>
<h3><%= @user.name %></h3>
<h3><%= @user.email %></h3>

Lastly we need to implement routing for the subdomains. Create a class like this:

class Subdomain
  def self.matches?(request)
    case request.subdomain
    when 'www', '', nil
      false
    else
      true
    end
  end
end

Make sure this class is autoloaded when the application starts `config/application.rb`:

config.autoload_paths += %W(#{config.root}/lib)

Ensure your `routes.rb` file contains the following routes:

devise_for :users
resources :users, :only => :show
constraints(Subdomain) do
  match '/' => 'profiles#show'
end

If you used `rails generate` for your profiles controller - ensure that you remove the `get "profiles/show"` route.

See this page for information on using URL Helpers in your application (essentially you'll need to use `new_user_session_url` instead of `new_user_session_path` and you can specify a subdomain like this:

root_url(:subdomain => @subdomain)

Problem

I would like to have Devise create subdomains on my site. Right now, I have two models: Company: A `Company` can register directly on the site, and after signing in, can invite their employees. When the company registers, I want a unique subdomain to be created (e.g. example.com => techcraz.example.com.) Employee: An `Employee` can register only if they received an invitation link. What I would like: - The main domain as a registration page. - A single sign in page for both `Companies` and `Employees`. - When signing in they must provide a domain name then they should be redirected to the sign in page for that subdomain (e.g. techcraz.example.com/signin.) - When entering a URL that does not exist, they should be redirected to the registration page. I am new to Rails. Please help! Thanks in advance!

Original source