Devise current_user with single table inheritance - ruby-on-rails

I have a user model with an admin submodel.
class Admin < User
end
I have devise set up and a 'type' column in the user model. The routes look like this:
devise_for :users, :controllers => { :sessions => 'sessions' }, :skip => :registrations
devise_for :admins, :skip => :sessions
I am unclear on how to override devise so I can access an admin using the current_user helper.
Right now name is undefined from <%= current_user.name %>
Is an admin not also a user? I'm not sure why current_user is nil.
In my sessions_controller I have:
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

Related

Devise after confirmation form uninitialized constant error

This app is being built on Devise 3.0 and Rails 4.1
I have a User object with two subclasses (Lender and Business) through STI. After a Business registers and confirms their email address, they are redirected to a form to fill out more information about themselves (This data is stored in a new object called SuppForm).
A business object has_one supp_form. I'm getting an error when the business confirms their email and is redirected to the form.
The error
ActionController::RoutingError (uninitialized constant SuppFormsController)
routes.rb (I used [ ] for business routes because I don't want them overlapping with the routes used in other places of the application)
# User type routes, needed to define specific sign out route to allow get request, not delete request
devise_for :users, skip: :registrations do get '/users/sign_out' => 'devise/sessions#destroy' end
devise_for :lenders, skip: :sessions, :controllers => {:registrations => "lenders/registrations"}
devise_for :businesses, skip: :sessions, :controllers => {:registrations => "businesses/registrations"}
resources :businesses, :only => [] do
resource :supp_form
end
business.rb
class Business < User
has_one :supp_form
accepts_nested_attributes_for :supp_form
end
supp_form.rb
class SuppForm < ActiveRecord::Base
belongs_to :business
end
supp_form_controller.rb
class SuppFormController < ApplicationController
before_filter :authenticate_user!
def new
#suppform = SuppForm.new
end
private
def supp_form_params
params.require(:supp_form).permit(:first_name, :last_name, :work_phone_number, :business_address, :business_postal_code)
end
end
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
def account_url
return new_user_session_url unless user_signed_in?
case current_user.class.name
when "Business"
business_root_path
when "Lender"
lender_root_path
else
root_path
end if user_signed_in?
end
def after_sign_in_path_for(resource)
if resource.sign_in_count == 1 && resource.type == "Business"
new_business_supp_form_path(resource.id)
else
stored_location_for(resource) || account_url
end
end
You can see in application_controller.rb I redirect the business to the supp_form based on the number of times they've logged in. I also try and pass through the business's ID by calling resource.id and passing that through the request. The URL when I get the error is: http://xxxxxxxxxx/businesses/14/supp_form/new
Looks like a pluralization problem. Change the controller to a plural name.
class SuppFormsController < ApplicationController
before_filter :authenticate_user!
# etc
end
Does sound weird though since there really is only a single supp_form generated from the controller. You could also try to setup inflections to prevent rails from attempting to pluralize the word supp_form in config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
inflect.uncountable %w( supp_form )
end

Devise after sign in/out inside of Mountable Engine redirecting to parent app rather than Engine

After sign in or sign out with Devise, I'm redirected back to the parent app root_path rather than my engine's root path (or, as you can see below, where I tried to specify it to home_path).
Engine routes:
MyEngine::Engine.routes.draw do
devise_for :users, {
:class_name => "MyEngine::User",
:module => :devise
}
get '/' => 'home#index', as: :home
root :to => 'home#index'
end
Engine Application Controller:
module MyEngine
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
home_path
end
end
end
Thanks...
The problem was not having namespaced the sessions controller. Specifying the controller explicitly in the engine, and having it namespaced correctly fixed the issue.
Routes:
MyEngine::Engine.routes.draw do
devise_for :users, {
:class_name => "MyEngine::User",
:module => :devise,
:controllers => { :sessions => "my_engine/sessions" }
}
end
SessionsController in 'controllers/my_engine/sessions_controller':
module MyEngine
class SessionsController < ::Devise::SessionsController
end
end

Sharing RegistrationController for two devise models

I have two devise models, Individual and Group. I'm trying to share similar behavior for Registrations/Confirmations (send users to a page that informs them that an email has been sent, or send them to the edit page after confirmation, etc.)
My issue is that this works for Individuals, only. It has yet to work for Groups.
config/outes.rb:
devise_for :individuals, :controllers => {:confirmations => "Confirmation", :registrations => "Registrations"}
devise_for :groups, :controllers => {:confirmations => "Confirmation", :registrations => "Registrations"}
app/controllers/registrations_controller.rb:
class RegistrationsController < Devise::RegistrationsController
def after_inactive_sign_up_path_for(item)
"/post_sign_up?email=#{item.email}"
end
end
app/controllers/confirmation_controller.rb:
class ConfirmationController < Devise::ConfirmationsController
def after_confirmation_path_for(name, resource)
case resource.class
when Individual then edit_individual_path resource
when Group then edit_group_path resource
else super name, resource
end
end
end
The above code works for individuals, only. Can't figure out why though.
I was focused so heavily on the provided lines in routes.rb, I failed to notice another "devise_for :groups" at the top of the file. Apparently devise will override previous values in this case. Stupid mistake.
for scale & no errors - better to devide.
admin_registration_controller.rb:
class AdminRegistrationsController < Devise::RegistrationsController
end
user_registration_controller.rb:
class UserRegistrationsController < Devise::RegistrationsController
end
routes:
devise_for :admins, controllers: { registrations: 'admin_registrations' }
devise_for :users, controllers: { registrations: 'user_registrations' }

Route for custom action in controller inheriting from Devise::SessionsController

I have a session controller which inherits from Devise::SessionsController:
class SessionsController < Devise::SessionsController
skip_before_filter :authenticate_user!, :only => [:get_token]
def create
....
end
def destroy
...
end
def get_token
response.headers["app-key"] = form_authenticity_token()
render :text=>'Token Set'
end
end
As you can see above i am overwriting create and destroy action and i have added another action named get_token. I added routes for it as shown below:
Routes.rb
Application.routes.draw do
devise_for :users, :controllers => { :sessions => "sessions" }, :path => "users", :path_names => { :sign_in => 'login', :sign_out => 'logout',:confirmation => 'verification'}
match 'get_token', :to => 'sessions#get_token'
But I am getting the following errror when i am trying to access get_token method;
[Devise] Could not find devise mapping for path "/get_token".
How to add route for the get_token action.
Thanks in advance
You need to scope the route in Devise like so:
devise_scope :user do
get 'get_token' => 'sessions#get_token'
end
That should allow you call http://your-url/get_token to access that action.

Devise custom registrations controller error

When I try to create a custom devise controller:
class RegistrationsController < Devise::RegistrationsController
def new
super
end
def create
# add custom create logic here
end
def update
super
end
end
I get a following error:
Unknown action
AbstractController::ActionNotFound
It is not the problem with routes. I tried to inherit RegistrationsController from ApplicationController and it works fine. As soon as i try to inherit from Devise::RegistrationsController it shows an error. It can't be an action problem to, becuse I tried to create a different action, and I get the same error.
# app/config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
root :to => "registrations#new"
Using Rails 3.0.4
In your routes you have to use devise_scope if you are overriding devise default actions.
devise_for :users, :controllers => {:registrations => "registrations"}
devise_scope :user do
root :to => "registrations#new"
end
For a similar issue please see http://groups.google.com/group/plataformatec-devise/browse_thread/thread/a5beaaf4b1ad343a
Also here are the docs on changing default sign in routes, I know this you are doing registration, but this could be similar: https://github.com/plataformatec/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes
I used the following code in my project successfully:
app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
end
routes.rb
devise_for :users, :controllers => { :registrations => "users/registrations" }

Resources