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...!!!
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'm trying to use before_action :authenticate_admin! to determine if the current user is an admin or not. I am using devise with single table inheritance (STI).
Here is my User model;
class User < ApplicationRecord
def admin?
false
end
devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :lockable
end
And my Admin model;
class Users::Admin < User
def devise_scope
:admin
end
def admin?
true
end
end
Just to test out devise, I have this in my routes file;
authenticated :user, ->(u) { u.admin? } do
resources :teams
end
And indeed, if I am signed in as a different User type (so not Admin), I can't get to that resource.
But this fails to work;
class Teams < ApplicationController
before_action :authenticate_admin!
def index
end
end
I get the error;
undefined method `authenticate_admin!'
Quite new to Rails so I don't understand how to resolve this.
UPDATE
I had to put this in the routes file;
devise_for :admins, class_name: 'Users::Admin'
Previously I only had;
devise_for :users, controllers: {sessions: 'users/sessions'}
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.
i'm working on a Ruby on Rails application and using devise to authenticate user.
First of all, i have these models:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :lockable
end
class Admin < User
end
class Partner < User
end
My devise_for on routes:
devise_for :users, :controllers => {
:registrations => "registrations",
:passwords => "passwords"
}
What i want to do? I want do a separate devise for each model, with different views and different strategy, for example: The user login with his registration number and password, the admin and the partner login with email and password (i think that admin and partner devise can be the same, because thier login stratagy is the same).
What is the best way to do this?
Configure routes:
devise_for :users
devise_for :admins
devise_for :partners
Generate devise views
rails generate devise:views user
rails generate devise:views admin
rails generate devise:views partner
Don't forget, add type field in users table for your STI
class AddTypeToUser < ActiveRecord::Migration
def up
add_column :users, :type, :string
end
def down
remove_column :users, :type
end
end
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.