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: