I have devise wich authenticates a user. User
is split up into subclasses such as User::AsProfile < User
or User::AsRegistrant< User
. These are not Single Table Inheritance classes, just plain old ruby-objects that inherit from User.
I'd like devises' current_user
helper to return an instance of User::AsProfile.
Unfortunately, Device has a lot of metaprogamming hidden away in class_eval
so it is hard to understand what is going on.
Can I configure Devise to return another class (User::AsProfile) when running current_user
in a controller?
Or must I override current_user
in my controller to do so, and if so, how should I call warden to authenticate properly?
I ended up re-implementing current_user
in my ApplicationController.
Since I don't need the ability to have one user use multiple sessions, I could simplify the current_user
a lot:
class ApplicationController < ActionController::Base
def current_user
return @current_user if @current_user
current = warden.authenticate(scope: :user)
@current_user = current.becomes(User::AsProfile) if current
end
end
By using ActiveRecords becomes
, the user is turned into a User::AsProfile
. I'd rather not have this conversion and use User::AsProfile#find
directly, but that seems only possible whith monkeypatching Warden.
As a sidenote: This problem shows well what happens when a library implements a poorly designed class-inheritance; or, in this case, no inheritance at all. The Devise code simply monkeypatches your ApplicationController and adds methods there. Never a good idea. With hindsight, Devise should simply be some modules (Concerns) that a developer can pick-and-choose and add to his controllers.