Skip to main content
Common Features in Rails Apps:

Tracking online users with timestamps

Episode 330 · February 3, 2020

We can use timestamps in our database to track of online users in your Rails

ActiveRecord


Keeping track of users who are "online" in your application can be done in several different ways.

This episode, we're going to implement a simple version of online user tracking by storing a timestamp of the last request the user has made. We can estimate which users are online by simply querying for any users who are online in the last 5 minutes. Depending on how accurate we want to be, we can adjust this window to be 1 minute or 15 minutes to be more or less accurate.

No matter what you do, you'll end up with an estimation here. The user could leave a tab open in their browser for 8 hours and they would be considered "offline" after 5 minutes.

Next episode, we'll talk about using ActionCable and having a websocket provide realtime updates of user's online status.

Resources

Transcripts

Earn a free month

What's up guys, this episode we're going to be exploring how to keep track of the online users on your Rails app. Now we're going to be doing a two-part series on this where the first episode we're going to do a very rudimentary, simple version of it where we're going to keep track of everything using a before_action and a model column in the database. It'll be very straight-forward.

The second version, which we're going to be talking about in part 2, is going to be using ActionCable to keep track in real time which users are active on your site. So, those will happen instantaneously and will work more similarly to the way that Slack works when you're seeing users come online and go offline.

Implementing Model and Controller Logic

Let's dive into our first version with our database model. So we're using the Jumpstart template here. We have a user model that we can log into using Devise. That's going to be the foundation for this. What we'll need to do is to generate the following migration:

# command line

>> rails g migration AddLastSeenAtToUsers last_seen_at:datetime

We'll generate this migration and run the following to create that column:

# command line

>> rails db:migrate

Then, once this is done, we can go ahead and open up our editor. Our model can have the following scope:

# app/models/user.rb

class User < ApplicationRecord
    # Irrelevant code is ommitted for space
  scope :online, ->{ where("last_seen_at > ?", 15.minutes.ago) }
end

This will return all of the users where last_seen_at is greater than a certain timestamp. You can make this however accurate you want. For instance, you could use 1, 5, or 10 minutes. You can change this number to whatever is most practical for your use case. So, this example will give you an idea of users who are online in the last 15 minutes.

For us to actually set this when you're navigating around the application, we're going to want a before_action in our ApplicationController.

# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  # Irrelevant code is ommitted for space
  before_action :set_last_seen_at, if: :user_signed_in?

  protected

    def set_last_seen_at
      current_user.touch(:last_seen_at)
    end
end

It should be noted that user_signed_in? is set automatically as a Devise helper. This code will update our database record so that it will continuously update last_seen_at accordingly.

Adding View Logic to the App

Now we can go to our index action and display on the homepage which users are online.

<!-- app/views/home/index.html.erb-->

<h1>Users Online</h1>

<ul>
  <% User.online.each do |user| %>
    <li><%= user.name %></li>
  <% end %>
</ul>

Once we have all of this on the page, we should be good to go. So, we can go into our browser, and once we run our Rails server, we'll be able to log in as user and see the users that are currently online. We are currently logged in as excid3 in one browser, and we aren't logged in on the other. If we were to log in as [email protected] this will be a separate user account, and it will be marked as online.

If the other user refreshes, then they'll both be shown as online, and they'll be able to see that. It's not going to update in real time or anything, but it is going to keep track of that so that we can easily query the database when we want to render this out.

If we were to go and update the last_seen_at time for the second user to twenty minutes ago, this is going to put them outside of the timestamp window, and if we refresh the page for the other user, we'll see that excid3 goes offline. The code to do this is listed below.

# Inside a rails console session

User.last.update(last_seen_at: 20.minutes.ago)

That user is no longer online because their timestamp is outside that window. So, if they stop making requests to our app, we stop seeing them as marked online.

Concluding Thoughts

It's a very simple, rudimentary example on how to keep track of whether or not you have users online. It's not going to be super accurate, but it is going to keep track of the last request that they had, which might be all you need. It's very simple, and it doesn't add much code to your application.

The ActionCable version that we'll talk about in the next part of this series is going to get a little more in-depth, because we're going to have to connect to ActionCable. We'll also talk about how to update those statuses and users online in real-time. We'll add Javascript and ActionCable broadcasts to actually say, "Hey, this user's now online, and this user's now offline". We'll be able to sync all of that using ActionCable which will give us a more real-time feel for active, online users.

Loading...

Subscribe to the newsletter

Join 31,353+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.