See if User is online using Devise in Ruby on Rails
Tags: ruby, rails, authentication, ux
Published: 2021-08-02 23:55:53

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](https://stackoverflow.com/a/5504188/12595487) 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](https://www.ryanepp.com/blog/how-do-i-tell-if-a-user-is-online) 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;
```ruby
rails generate devise User
```
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`.

```ruby
#application_controller.rb

after_action :update_user_online, if: :user_signed_in?

private

def update_user_online
  current_user.try :touch
end
```

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

```ruby
#user.rb

def online?
  updated_at > 2.minutes.ago
end
```
Now we can get `true` or `false` if we make a call like `@user.online?`

```ruby
#users/show.html.erb

<%= @user.online? %>
```

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](https://stackoverflow.com/questions/10805479/rails-how-to-check-for-online-users) [2](https://stackoverflow.com/questions/3184973/rails-using-devise-to-show-online-users) [3](https://stackoverflow.com/questions/20821341/rails-how-to-show-users-last-seen-at-time) [4](https://www.ryanepp.com/blog/how-do-i-tell-if-a-user-is-online) [5](https://blog.corsego.com/set-user-status-online)