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
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.
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.
Well, this solution is related to Devise.
When we create a User Model based on Devise;
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.
current_user does any action, his
updated_at will be set as
#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
#user.rb def online? updated_at > 2.minutes.ago end
Now we can get
false if we make a call like
#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.