I have two type of users: master and customer (like freelance). I use devise gem.
How to create two ways of registration easier?
The best is to create a STI
class User < ActiveRecord::Base
end
class User::Master < User
end
class User::Customer < User
end
Install devise gem
rails g devise:install
Configure routes:
devise_for :users, skip: [:registrations]
devise_for :masters, skip: :sessions
devise_for :customers, skip: :sessions
Generate devise views
rails g devise:views
After you create helpers for the methods currency but adapting them to STI.
Related
I have multiple models which are using devise like Admin, Student and Counselor
I don't want to use roles as it 'll complicate things in this case.
I want to use one layout and show menus etc. depending upon class of model like
= render "shared/#{resource.class}_menu"
Is there way that I can get class of logged in object without if else conditions like we do in after_sign_in_path_for etc.
So what I do in this case where you want to have different areas for Admin, Student and Counselor
you can namespace each role or log in like this
#config/routes.rb
Rails.application.routes.draw do
devise_for :admins, :controllers => { registrations: 'admins/registrations',
sessions: 'admins/sessions',
passwords: 'admins/passwords',
confirmations: 'admins/confirmations'
}
authenticate :admin do
namespace :admins do
....
root :to => 'something#index'
end
end
devise_for : students, :controllers => { registrations: 'students/registrations',
sessions: 'students/sessions',
passwords: 'students/passwords',
confirmations: 'students/confirmations'
}
authenticate :student do
namespace :students do
....
root :to => 'something#index'
end
end
Now you can create the devise model for each namespace.
#app/controllers/admin_controller.rb
class AdminController < ApplicationController
before_filter :authenticate_admin!
end
For Devise controllers you can use them like tihs
#app/controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
end
For basic application controllers, you can use them like this.
#app/controllers/users/somethings_controller.rb
class Users::SomethingsController < UserController
...
end
I hope that this is able to help you
I am working on Mongoid and Rails4
I have model structure (STI) like this,
Class User
devise :database_authenticatable, :registerable
end
User Class is having devise functionality
class Teacher < User
end
class Student < User
end
In route.rb,
devise_for :users
devise_for :teachers, :skip => :sessions
devise_for :students, :skip => :sessions
In a student_profile controller i have defined,
before_filter :authenticate_student!
After signed in as "student" if i clicks on student_profiles_path its redirecting to root file. In database user type is storing as "type" : "Student", while sign up i am passing the _type value via collectionselect.
Is there any setting or code stuff i have to do...!!!
I just made a new app, and am wondering how I would route it. A user has_many companies,but how how do I route it so? I am using devise.
::Application.routes.draw do
devise_for :users do
resources :companies
end
root :to => "home#index"
end
I'd suggest separating between devise routes and other app routes:
devise_for :users, :path => 'accounts'
resources :users do
resources :companies
end
This also means that devise will use /accounts/* instead of /users/* for its authentication paths and so /users/* will remain free for your use.
You can also look at devise's routing documentation.
I use devise, and I want generate a new object scaffold under devise user sth like:
resources :users, :path => "/", :only => [:show] do
resources :collections, :controller => 'users/collections'
end
With above routes, I get this url:
http://localhost:3000/kevin_doe/collections
The problem is that if I issue this command:
rails g scaffold users/collection title:string description:text
This generate a namespace sth like:
namespace :users do resources :collections end
The route that I get is:
http://localhost:3000/users/collections
I want generate a scaffold under devise user resource.
How can I fix this problem?
Thank you!
The fix for this question are the next steps:
1º generate the scaffold with:
rails g scaffold collection title:string description:text
2º Modify your routes.rb file with the nested resource:
resources :users, :path => "/", :only => [:show] do
resources :collections, :controller => 'users/collections'
end
3º you must create a "users" folder in your controllers directory and move the collections_controller.rb to
app/controllers/users/
4º in collections_controller.rb you must modify:
class Users::CollectionsController < ApplicationController
.
.
.
end
5º In your views you must move the folder collections to app/views/users/collections
Done! :D.
I am having a problem getting Devise to work the way I'd like with single table inheritance.
I have two different types of account organised as follows:
class Account < ActiveRecord::Base
devise :database_authenticatable, :registerable
end
class User < Account
end
class Company < Account
end
I have the following routes:
devise_for :account, :user, :company
Users register at /user/sign_up and companies register at /company/sign_up. All users log in using a single form at /account/sign_in (Account is the parent class).
However, logging in via this form only seems to authenticate them for the Account scope. Subsequent requests to actions such as /user/edit or /company/edit direct the user to the login screen for the corresponding scope.
How can I get Devise to recognise the account 'type' and authenticate them for the relevant scope?
Any suggestions much appreciated.
There is an easy way to handle STI in the routes.
Let's say you have the following STI models:
def Account < ActiveRecord::Base
# put the devise stuff here
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
def User < Account
end
def Company < Account
A method that is often overlooked is that you can specify a block in the authenticated method in your routes.rb file:
## config/routes.rb
devise_for :accounts, :skip => :registrations
devise_for :users, :companies, :skip => :sessions
# routes for all users
authenticated :account do
end
# routes only for users
authenticated :user, lambda {|u| u.type == "User"} do
end
# routes only for companies
authenticated :user, lambda {|u| u.type == "Company"} do
end
To get the various helper methods like "current_user" and "authenticate_user!" ("current_account" and "authenticate_account!" are already defined) without having to define a separate method for each (which quickly becomes unmaintainable as more user types are added), you can define dynamic helper methods in your ApplicationController:
## controllers/application_controller.rb
def ApplicationController < ActionController::Base
%w(User Company).each do |k|
define_method "current_#{k.underscore}" do
current_account if current_account.is_a?(k.constantize)
end
define_method "authenticate_#{k.underscore}!" do
|opts={}| send("current_#{k.underscore}") || not_authorized
end
end
end
This is how I solved the rails devise STI problem.
I just ran into the exact scenario (with class names changed) as outlined in the question. Here's my solution (Devise 2.2.3, Rails 3.2.13):
in config/routes.rb:
devise_for :accounts, :controllers => { :sessions => 'sessions' }, :skip => :registrations
devise_for :users, :companies, :skip => :sessions
in app/controllers/sessions_controller.rb:
class SessionsController < Devise::SessionsController
def create
rtn = super
sign_in(resource.type.underscore, resource.type.constantize.send(:find, resource.id)) unless resource.type.nil?
rtn
end
end
Note: since your Accounts class will still be :registerable the default links in views/devise/shared/_links.erb will try to be emitted, but new_registration_path(Accounts) won't work (we :skip it in the route drawing) and cause an error. You'll have to generate the devise views and manually remove it.
Hat-tip to https://groups.google.com/forum/?fromgroups=#!topic/plataformatec-devise/s4Gg3BjhG0E for pointing me in the right direction.
try to change routes like so:
devise_for :accounts, :users, :companies
because Devise uses plural names for it's resources
Please let me know if it help you
I don't think this is possible without overriding the sessions controller. Each sign_in page has a specific scope that devise will authenticate against as defined by your routes.
It may be possible to use the same sign_in page for multiple user scopes by using the devise_scope function in your routes file to force both :users and :companies to use the same sign in page (a how-to can be found here), but I'm pretty certain that you would have to modify your sessions controller to do some custom logic in order to determine which type of user is signing in.