问题
In a Rails app that uses Devise, is there a way to tell if a specific user is signed in right now?
I know about the view helper, user_signed_in?. What I'm looking for is more like:
User.all.each do |user|
puts user.signed_in?
end
I see that Devise has added a current_sign_in_at column to users. But that doesn't get set to NULL when the user signs out, so I can't test with that.
How can I check whether a user is currently signed in?
回答1:
You can add a before_filter to your ApplicationController to set the current date/time in the last_request_at field in your users table, which you'd have to add first via a migration. In the method called from the before_filter, you wanna make sure that the user is authenticated first, of course. And you may want to except the filter for actions not requiring authentication.
Then, assuming you've included the Timeoutable module in your User model, you can see if the user's session is current or not by making a call like this:
user.timedout?(user.last_request_at)
The timedout?(last_access) method, defined in the Timeoutable module, will compare the Devise session timeout with the last request time/date.
As a side note, you might want to only update last_request_at if the last last_request_at value is greater than a minute ago (or any time interval you choose). Otherwise, if your page makes lots of controller calls, like mine does via AJAX, there are a lot of unnecessary db updates in one request.
回答2:
Are you trying to track if the user is signed in and has a session active, or if the user is on the site right now?
For tracking if the user is signed in, you would need to add a callback to Warden and update a timestamp every time a page loads and then if they haven't done anything for longer than X time period you assume they are logged out. You can do this with:
Warden::Manager.after_authentication do |user, auth, opts|
if user.last_action <= 5.minutes.ago.utc
user.last_action = Time.now
user.save
end
end
If you want to see if the have an active season and haven't explicitly logged out, it would be something such as:
Warden::Manager.before_logout do |user, auth, opts|
user.current_sign_in_at = nil
user.save
end
回答3:
Add an active flag to your user (devise) model. In the application controller under the after_sign_in_path_for(resource) hook set the active flag to true(happens when the user successfully creates a new session).
for loged out user, override the destroy method in the devise session_controller and set the active flag to false, then call super.
Now you can call user.active? on any user.
回答4:
Devise comes with a method current_user that will return the current user in controllers, models, and views.
来源:https://stackoverflow.com/questions/8837784/how-can-i-tell-whether-a-given-devise-user-is-signed-in-right-now