Prácticamente hay dos formas de manejar múltiples roles en una aplicación en Rails.

La más común es con un modelo de usuarios y un atributo rol que permita distinguir el tipo de usuario, la segunda forma es con múltiples tablas, una para cada tipo de usuario distinto, y es la que abordaremos en este tutorial.

Separar las tablas (y por lo mismo los modelos) tiene sentido cuando la lógica (los métodos que implementemos) sean muy distintos para cada tipo de usuario.

Para esta demostración necesitamos un proyecto en rails con devise agregado como gema y dos modelos deviseables, si ya los tienes pasa al siguiente paso

Setup de devise y creación de los modelos devisebles

Agregamos al gemfile:

gem devise

Acto seguido en el terminal hacemos bundle:

bundle install

Utilizamos el generador de rails para crear los archivos iniciales y de configuración de devise:

rails generate devise:install

Y ahora generaremos el primer modelo al que llamaremos user:

rails generate devise user

y finalmente generaremos un segundo modelo llamado company:

rails generate devise company

 Manejando múltiples usuarios

Si ahora vemos nuestras rutas veremos que cada modelo tiene su propio login, son formularios distintos, con rutas distintas y se procesan en rutas distintas, por lo que practicamente estamos listos

        new_company_session GET    /companies/sign_in(.:format)       devise/sessions#new
            company_session POST   /companies/sign_in(.:format)       devise/sessions#create
    destroy_company_session DELETE /companies/sign_out(.:format)      devise/sessions#destroy
           company_password POST   /companies/password(.:format)      devise/passwords#create
       new_company_password GET    /companies/password/new(.:format)  devise/passwords#new
      edit_company_password GET    /companies/password/edit(.:format) devise/passwords#edit
                            PATCH  /companies/password(.:format)      devise/passwords#update
                            PUT    /companies/password(.:format)      devise/passwords#update
cancel_company_registration GET    /companies/cancel(.:format)        devise/registrations#cancel
       company_registration POST   /companies(.:format)               devise/registrations#create
   new_company_registration GET    /companies/sign_up(.:format)       devise/registrations#new
  edit_company_registration GET    /companies/edit(.:format)          devise/registrations#edit
                            PATCH  /companies(.:format)               devise/registrations#update
                            PUT    /companies(.:format)               devise/registrations#update
                            DELETE /companies(.:format)               devise/registrations#destroy
           new_user_session GET    /users/sign_in(.:format)           devise/sessions#new
               user_session POST   /users/sign_in(.:format)           devise/sessions#create
       destroy_user_session DELETE /users/sign_out(.:format)          devise/sessions#destroy
              user_password POST   /users/password(.:format)          devise/passwords#create
          new_user_password GET    /users/password/new(.:format)      devise/passwords#new
         edit_user_password GET    /users/password/edit(.:format)     devise/passwords#edit
                            PATCH  /users/password(.:format)          devise/passwords#update
                            PUT    /users/password(.:format)          devise/passwords#update
   cancel_user_registration GET    /users/cancel(.:format)            devise/registrations#cancel
          user_registration POST   /users(.:format)                   devise/registrations#create
      new_user_registration GET    /users/sign_up(.:format)           devise/registrations#new
     edit_user_registration GET    /users/edit(.:format)              devise/registrations#edit
                            PATCH  /users(.:format)                   devise/registrations#update
                            PUT    /users(.:format)                   devise/registrations#update
                            DELETE /users(.:format)                   devise/registrations#destroy

Pero con una sola gran pregunta pendiente, ¿Cómo podemos saber si un usuario está logeado?

Este podría ser una empresa o un usuario corriente, entonces podemos utilizar los helpers incluídos de devise como user_signed_in? y company_signed_in?, pero también tendremos un current_user y un current_company y nuestro código comienza a ser más complejo de manejar y se vuelve muy complejo con más de dos tipos de usuarios.

Para resolver este problema agregaremos al application controller

devise_group :entity, contains: [:user, :company]

Luego en lugar de utilizar current_user o current_company podemos utilizar current_entity

Por ejemplo si ingresamos al sistema como una compañía y mostramos current_entity veremos:

company