"Who's Online" using Devise in Rails
Asked Answered
T

5

44

Using Devise on Rails, is there some way to list all the users who currently have active sessions i.e. the users that are currently logged in?

Ps. I'm looking for a robust solution, not something simplistic like the ones in this question

Tenuous answered 31/3, 2011 at 17:52 Comment(1)
I found this answer very useful: #20821841Efflux
G
25

https://github.com/ctide/devise_lastseenable

You can use this gem that I wrote to store the 'last_seen' timestamp of a user. From there, it's pretty trivial to display the users who were last_seen in the last 5 or 10 minutes.

Gowen answered 31/3, 2011 at 17:56 Comment(2)
could you give code of display the users who were last_seen in the last 5 or 10 minutes. ?Eau
User.where('last_seen > ?', 5.minutes.ago)Gowen
T
87

Simply add after_filter in ApplicationController

after_filter :user_activity

private

def user_activity
  current_user.try :touch
end

Then in user model add online? method

def online?
  updated_at > 10.minutes.ago
end

Also u can create scope

scope :online, lambda{ where("updated_at > ?", 10.minutes.ago) }
Tenorite answered 15/12, 2011 at 10:43 Comment(6)
Would devise_lastseenable still work with rails 3.2 and Devise 2.0?Toweling
@Toweling I don't know, but this solution is so simple I'd rather use it than add extra dependencies which could break in future releases of rails or devise.Edlun
Isn't this going to run SQL on every action?Selfpossession
This was a great suggestion. Because touch sets the updated_at column, it could produce a false positive if you use the general column updated_at to see who is online. For example, adjusting someone's user profile would falsely show them as online for 10 minutes. We used current_user.try(:touch, :last_response_at) and added this new field to the database with a migration. We also set this to nil on sessions#destroy so they drop out anytime the user explicitly logs out. Last but not least, we made sure to add an index for the new field.Doityourself
I like this solution, but I'm a bit confused on implementing it. If I'm trying to determine if the current_user is online (say they had multiple tabs and logged out on one of them), is there a way to use this without refreshing the page?Southard
@yuribarbashov how does that compare to this? ryanepp.com/blog/how-do-i-tell-if-a-user-is-onlineEquine
G
25

https://github.com/ctide/devise_lastseenable

You can use this gem that I wrote to store the 'last_seen' timestamp of a user. From there, it's pretty trivial to display the users who were last_seen in the last 5 or 10 minutes.

Gowen answered 31/3, 2011 at 17:56 Comment(2)
could you give code of display the users who were last_seen in the last 5 or 10 minutes. ?Eau
User.where('last_seen > ?', 5.minutes.ago)Gowen
P
20

If you're bothered by making a trip to database on every. single. http. request. only to have some small window where you can sort of assume that a user is online; I have an alternate solution.

Using websockets and redis it's possible to reliably get a user's online status up to the millisecond without making a billion costly writes to disk. Unfortunately, it requires a good bit more work and has two additional dependencies, but if anybody's interested I did a pretty detailed write here:

How do I tell if a user is online?

Penitentiary answered 28/1, 2014 at 4:21 Comment(3)
can it be wrap into gem?Troop
Thanks! I set up this in 15 minutes and this works fine!Racer
Ryan, your blog post is great, but can you summarize it succinctly here so that if your blog/link ever dies, your method isn't lost forever?Belldame
X
1

I've just implemented another version of this and thought I'd share in case it helps anyone else.

I just add a last_sign_out_at column to my Users table and then subclassed the Devise sessions controller so I could override the destroy method to set it when the session is destroyed (user signs out):

# app/controllers

class SessionsController < Devise::SessionsController

  def destroy
    current_user.update_attribute(:last_sign_out_at, Time.now)
    super
  end

end

And then in my User model I have a method to check if the user is online:

class User < ActiveRecord::Base

  def online?
    if current_sign_in_at.present? 
      last_sign_out_at.present? ? current_sign_in_at > last_sign_out_at : true
    else
      false
    end
  end

end

Also you need to tell Devise to use the new Sessions controller in your routes.

Ximenez answered 1/2, 2013 at 9:6 Comment(1)
This is not a very good solution (at least not alone), as most user won't sign out, just close the browser or leave the site.Baerl
R
0

We can list the current active sessions using the active record session store. Please look at the github app page https://github.com/mohanraj-ramanujam/online-users.

Ramah answered 15/7, 2013 at 4:57 Comment(1)
Maybe you could supply some documentation?Lordsandladies

© 2022 - 2024 — McMap. All rights reserved.