Search code examples
ruby-on-railsruby-on-rails-3devisesingle-table-inheritance

Rails: Using Devise with single table inheritance


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.


Solution

  • 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.