DEV Community

Cover image for See if User is online using Devise in Ruby on Rails
Amirul Asyraf
Amirul Asyraf

Posted on

See if User is online using Devise in Ruby on Rails

Recently, I needed to figure out if a user was active(online) on my site. Because I hadn't done this before, I Googled for inspiration 🌈 but found little success 🙃. The majority of posts on Stack Overflow and blogs were variations of the same solution:

1) Add a last_online timestamp column to your User model, then define a scope for user called online_now.

Meaning, add new column to store on every timestamp the user is active/online. Then make a query(scope) from database which user that last active 2-10 minutes ago and display to the view.

This may take up some of your app's resources if you have many users who are logged in, because this will execute(update column & database query) before every controller action requested by someone who is logged in.

I think this process is slow.

2) devise_lastseenable Rubygems

Pretty old gems.

3) When someone has logged in, you can push him into an array, if someone has logged out, just remove him from the array.

I think last time I use this trick is on my Computer Science studies 😂 at universities long time ago.

4) WebSocket & Redis

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; There 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.

There is one article that explains well how to use this solution if you are interested.

But probably not my choice for a simple project.


So, What else ?

Well, this solution is related to Devise.

When we create a User Model based on Devise;

rails generate devise User
Enter fullscreen mode Exit fullscreen mode

Devise will create updated_at column with a datetime data type.

This is good tho. We can utilize already column from Devise instead of creating a new column like previous solution.

Whenever the current_user does any action, his updated_at will be set as Time.now.

#application_controller.rb

after_action :update_user_online, if: :user_signed_in?

private

def update_user_online
  current_user.try :touch
end
Enter fullscreen mode Exit fullscreen mode

And we will just say that the user is online if he was updated_at during the last 2.minutes or 1.minutes

#user.rb

def online?
  updated_at > 2.minutes.ago
end
Enter fullscreen mode Exit fullscreen mode

Now we can get true or false if we make a call like @user.online?

#users/show.html.erb

<%= @user.online? %>
Enter fullscreen mode Exit fullscreen mode

This is one of the best and simple solution I get when doing research and a little bit of experimentation.

I am very happy 😇 if you can share to me other tricks that is better than this.

The end


resources:

1 2 3 4 5

Top comments (2)

Collapse
 
superails profile image
Yaroslav Shmarov

haha! I opened your article with hope to find a better approach than mine, only to discover that my approach #5 is the one you found best!

This approach is very simple, although is very similar to #1 and is not super-scalable if there are very many users/requests

Collapse
 
asyraf profile image
Amirul Asyraf

😂 Haha. I found your article first which is simple and great, but I want to find if there is another solution. It ends with the same kind of solution.

I write this article hoping someone else gives another great approach. Your solution is still on the top :P. Thanks