Building A Visitor Tracker with Rails

In this article, we are going to build a visitor tracker app using Rails. The app will intercept the requests and show information like the client's IP, URL, path, and request method.

Requirements

  • Ruby installed

  • Rails installed

Creating a new Rails project.

First, we need to create a new rails project.

rails new visitor-tracker

Creating the model, database, controllers, and routes.

rails g resource  tracker

We go to db/migrate/<timestamp>create_trackers.rb to define the attributes of the tracker table. There will be eight attributes: IP address, request URL, port, path, method, browser, OS, time and the service name.

class CreateTrackers < ActiveRecord::Migration[7.0]
  def change
    create_table :trackers do |t|

      t.timestamps
      t.string :ip_address
      t.string :request_url
      t.integer :request_port
      t.string :request_path
      t.string :request_method
      t.string :browser_type
      t.datetime :request_time
    end
  end
end

We run the following command in our terminal, to migrate the table:

rails db:migrate

We go to app/controllers/tracker_controller.rb and create the functions to retrieve all the entries in the database, and to store the request info in the database.

Index

  def index
        @trackers = Tracker.all
        render json: @trackers
    end

Show

 def show
        @tracker = Tracker.find(params[:id])
        render json: @tracker
    end

Create

   def create
        @tracker = Tracker.create(
            ip_address: params[:ip_address],
            request_url: params[:request_url],
            request_port: params[:request_port],
            request_path: params[:request_path],
            request_method: params[:request_method],
            browser_type: params[:browser_type],
            request_time: params[:request_time],

        )
        render json: @tracker
    end

Complete trackers_controllers.rb file.

class TrackersController < ApplicationController
    def index
        @trackers = Tracker.all
        render json: @trackers
    end

    def show
        @tracker = Tracker.find(params[:id])
        render json: @tracker
    end

    def create
        @tracker = Tracker.create(
            ip_address: params[:ip_address],
            request_url: params[:request_url],
            request_port: params[:request_port],
            request_path: params[:request_path],
            request_method: params[:request_method],
            browser_type: params[:browser_type],
            request_time: params[:request_time],

        )
        render json: @tracker
    end    
end

In db/seed.rb we created a record to display when we make the GET request.

tracker_1 = Tracker.create(ip_address: "127.0.0.1", 
request_url: 'http://localhost:8000', request_port: 8000, request_path: "/",
request_method: "GET")

Then we run the following command to apply the changes.

rails db:seed

Now, let's start our server and see if it can show the data.

rails server

We navigate to localhost:port/trackers and we should see the following response in the browser or HTTP client:

Adding a middleware

We create a new folder, lib/middleware and create the lib/middleware/visitor_tracker file.

module Middleware
    class VisitorTracker
      def initialize(app)
        @app = app

      end

      def call(env)
        request = ActionDispatch::Request.new(env)

        Tracker.create(ip_address: request.ip, 
        request_url: request.original_url, request_port: request.port, request_path: request.path,
        request_method: request.request_method)

        @app.call(env)
      end
    end  
end

Here, we create our middleware, create the VisitorTracker class and create two methods, initialize and call.

In the call method, we create an instance of the ActionDispatch::Request class and then, create a new record in the database with the request information every time the middleware is executed.

Then, we go to config/application.rb file to declare our middleware.

require_relative "boot"
require_relative "../lib/middleware/visitor_tracker"

require "rails/all"


Bundler.require(*Rails.groups)

module Visitor
  class Application < Rails::Application

    config.load_defaults 7.0
    config.middleware.use Middleware::VisitorTracker

  end
end

Here we use the config.middleware.use method and pass the Middleware module and the VisitorTracker class. Rails will execute this middleware just before your application is called.

Now, to create a full-stack app, we need to go to config/routes.rb and paste the following code.

Rails.application.routes.draw do
  resources :trackers

  root "trackers#index"
  get "/trackers", to: "trackers#index"
end

Then, we need to go to the app/controllers/trackers_controllers.rb file and remove the code render json: @trackers from the index function. It should look like this:

def index
        @trackers = Tracker.all

end

Next, we go to the app/views/trackers folder and create the app/views/trackers/index.html.erb file.

<!DOCTYPE html>
<html>
    <head>
        <title>Visitor Tracker</title>
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <%= csrf_meta_tags %>
        <%= csp_meta_tag %>

        <%= stylesheet_link_tag "index", "data-turbo-track": "reload" %>
        <%= javascript_importmap_tags %>
    </head>
    <h1>Visitor Tracker</h1>
    <table>
        <tr>
            <th>IP Address </th>              
            <th>Request URL </th>                     
            <th>Request Port </th>  
            <th>Request Path </th>  
            <th>Request Method </th>

        </tr>
        <% @trackers.each do |tracker| %>
        <tr>
            <td><%= tracker.ip_address %></td>         
            <td><%= tracker.request_url %></td>     
            <td><%= tracker.request_port %></td>
            <td><%= tracker.request_path %></td>
            <td><%= tracker.request_method %></td>


        </tr>
        <% end %>
    </table>

</html>

We navigate to localhost:port/ and we should see the following response in the browser or HTTP client:

Next, we create the app/assets/stylesheets/index.css file and paste the following code.



table {
    border-collapse: collapse;
    margin-bottom: 1rem;
  }

  th,
  td {
    padding: 0.5rem;
    border: 1px solid #ccc;
  }

  th {
    text-align: left;
  }

  td {
    text-align: left;
  }

  .column-gap-10 {
    column-gap: 10px;
  }

Conclusion

In this article, we learned about how to build a visitor tracker with Rails and how to create custom middleware. With this app, we can see the activity of our applications.

The source code is here.

Thank you for taking the time to read this article.

If you have any recommendations about other packages, architectures, how to improve my code, my English, or anything; please leave a comment or contact me through Twitter, or LinkedIn.

Resources

Getting Started with Rails

Using Rails and HTML to View, Sort, and Search Tables.

Rails Middleware: (Almost) Everything You Need to Know