After 2 full days I have not been able to find a solution.
Here's my issue.
I created a rails app and added Devise. It all works great except for I have 3 devise users: Users
, Vendors
and Admin
.
My problem is that I am trying to create separate login pages for each user. However when I generate devise views and work on the login page it only pulls the HTML from the views/devise/sessions/new page. So whether you go /admin/sign_up
, /vendor/sign_up
or /user/sign_up
you get the exact same devise page from views/devise/sessions/new
.
How can you have 3 different devise/sessions/new views
? I want the User
login and sign up to look different from the Vendors
and Admin
logins. I have 3 devise controllers: Users_controller, Vendors_controller, and Admins_controller
I am soooo confused. Any help would be greatly appreciated.
Cheers,
You can generate three different devise models, views and controllers for Users
, Admins
and Vendors
. You can also add devise helpers to your existing models and controllers instead. For views, make sure to use Devise's role-scoped views generator:
`rails generate devise:views users` # change `users` to whichever role you are generating
Then you can route each role to its own signup
in routes.rb
using their devise_for
helper like so:
devise_scope :user do
get 'users/login' to: 'users#sessions#new', as 'user_login'
end
devise_scope :admin do
get 'admins/login', to: 'admins#sessions#new', as 'admin_login'
end
devise_scope :vendor do
get 'vendors/login', to: 'vendors#sessions#new', as 'vendor_login'
end
This is not very DRY. I would strongly suggest rethinking your design and creating a single model for User
with a role
attribute. Try the CanCan gem . Here is CanCan's wiki on how to create role-based authorization: https://github.com/ryanb/cancan/wiki/Role-Based-Authorization
Okay, several things to look at here.
First step is to get your models sorted out.
You mention you want to have Users
, Vendors
and Admin
. I am presuming you've made several models for this, and would like to stipulate now that it will be much more beneficial for you to inherit from one model.
The single model you need to use should be User
, and should extrapolate its functionality through an STI (Single Table Inheritance) :
#app/models/user.rb
class User < ActiveRecord::Base
#columns id | type | devise | attributes | created_at | updated_at
end
#app/models/admin.rb
class Admin < User
#No table necessary
end
#app/models/vendor.rb
class Vendor < User
#No table necessary
end
This will allow you to use each model as if it were completely standalone, yet maintaining the flexibility of extra functionality. I can explain more about it if you need; bottom line is that you'll be FAR better off using this than separate tables.
Next we have the views themselves.
The options you have for your views are as follows:
- Manage the selection with your routes & controllers
- Manage the selection in the views themselves
I would personally keep a single controller and use different views. You're using the same data, so all you need to is to either render different layouts , or different views entirely...
And, by the way, remember that Devise
uses its own controllers . For your purposes, these are Sessions
and Registrations
respectively:
#config/routes.rb
def devise_path_names
{ sign_in: "login", sign_up: "", registration: "register", sign_out: "logout" }
end
devise_for :users, path_names: devise_path_names #-> url.com/users/login
devise_for :admins, controllers: { sessions: "devise#sessions", registrations: "devise#registrations" }, path_names: devise_path_names #-> url.com/admins/login
devise_for :vendors, controllers: { sessions: "devise#sessions", registrations: "devise#registrations" }, path_names: devise_path_names #-> url.com/vendors/login
The above routes are untested.
It would be inadvisable to use your own controllers for the respective models - you'll have to recreate them each time, making it very WET . Instead, you'd be able to potentially do something like this:
#app/controllers/devise/sessions_controller.rb
class SessionsController < Devise::SessionsController
before_action :set_route
private
def set_route
@route = request.path.split('/')[0]
end
end
This would pass the params you require to the devise#sessions
controller.
Having said that, you could even just change the styling with the CSS classes in the views themselves:
$ rails generate devise:views users
#app/views/devise/sessions/new.html.erb
<%= form_for resource, as: resource_name, url: session_path(resource_name), class: @route do |f| %>
...
This will allow you to style the form as required in the CSS. It will pull the @route
param through the url, allowing you to set the styling in the view.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.