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.