I'm trying to create multiple models in Devise (using Ruby 2.0, Rails 4). I have searched Stack Overflow and tried Google, but most people end up using inheritance or CanCan.
The problem is that I need two entirely different models to be able to sign up and use my website, in two entirely different ways - one uses email or username to log in, and has all sorts of management abilities (such as seeing graphs of MobileUser usage, etc). The other will only access from a mobile device, uses a phone number to log in, and has a much simpler interface.
I tried to run Devise for both ('rails g devise WebUser' and 'rails g devise MobileUser'). I now have tables and columns for both, but only have routes and a model for the WebUser. I tried manually adding routes and a model for the MobileUser, but nothing works - the model doesn't connect to the table, the routes produce runtime errors ('WebUser does not respond to 'devise' method).
Everything I've read indicates that I can get Devise to work for two models on my one website - how do I implement this?
My routes:
Mailer::Application.routes.draw do
devise_for :web_users
# devise_for :mobile_users (doesn't work, so it is commented out)
resources 'web_users', only: [:show, :index]
resources 'mobile_users', only: [:show, :index]
root 'static_pages#home'
match '/contact', to: 'static_pages#contact', via: 'get'
match '/faq', to: 'static_pages#faq', via: 'get'
end
I know this is a very old question but maybe it will help to someone now in 2019 that Devise supports devise_group.
Thins makes really easy to work with multiple Devise models. I have three different devise models as show below:
User.rb
class User < ApplicationRecord
has_many :messages
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable
end
Organizer.rb
class Organizer < ApplicationRecord
has_one :organizer_profile, dependent: :destroy, autosave: true, inverse_of: :organizer
has_many :brochures, dependent: :destroy
has_many :messages, as: :messageable
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable
end
Sponsor.rb
class Sponsor < ApplicationRecord
has_one :sponsor_profile, dependent: :destroy, autosave: true, inverse_of: :sponsor
has_many :sponsorings
has_many :brochures, through: :sponsorings
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable
scope :approved, -> { where(approved: true) }
# Allow saving of attributes on associated records through the parent,
# :autosave option is automatically enabled on every association
accepts_nested_attributes_for :sponsor_profile
end
routes.rb
Rails.application.routes.draw do
# Deviseable resources
devise_for :organizers, controllers: {registrations: "organizers/registrations"}
devise_for :sponsors, controllers: {registrations: "sponsors/registrations"}
devise_for :users
root "welcome#index"
end
Now I can not use the same authenticate_user!, user_signed_in? or even current_user. So now, how can I know if any user is logged in? We may need to do something like user_signed_in? || organizer_signed_in? || sponsor_signed_in? but that's too much repeating code.
Thanks to devise_group option, we can simplify this workflow!
In your application_controller.rb add this:
class ApplicationController < ActionController::Base
# Devise working with multiple models.
# Define authentication filters and accessor helpers for a group of mappings.
devise_group :member, contains: [:organizer, :sponsor, :user]
private
def pundit_user
# Make Pundit to use whichever Devise model [Organizer, Sponsor, User] as the 'current_user'
# Just by using the offered helper method from Devise, 'devise_group' feature
current_member
end
end
Now you can use universal helpers authenticate_member!, member_signed_in? or even current_member to validate any Devise user when required. Or you can still user separated helper for each type of Devise user as normal.
Hope it could be useful for somebody!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With