Ruby on Rails implementation of a ranking system using PostgreSQL
This article will show how easily you can add ranking functionality to your project. We will accomplish it, with the use of ntile() window function. I will be using Ruby on Rails for my application, with PostgreSQL database.

Hello, this article will show, how easily you can add ranking functionality to your project. We will accomplish it, with the use of ntile()
window function. I will be using Ruby on Rails for my application, with PostgreSQL database.
We will need:
A model with integer attribute, by which we want to make the ranking (in my case, it’s
visit_count
). Here is an exemplary migration for Post model:tsx
Controller
tsx
Route for resource
tsx
View for our index action and partial for post
tsx
tsx
Here I won’t implement increment functionality for visit_count
, because it's not the case of this article. We will just generate data by ourselves. For example by running this in Rails console:
tsx
Instead of adding method to Post model, I will just create Query Object called PostWithPopularityQuery
, under app/query_objects/
, to keep the model slim.
tsx
You can see constant POPULARITY_RANGES
. This will be the number of 'levels' of popularity/ranking you want. Let's say it's 5. The ntile()
window function will then apply value in range 1-5 to each record. In other words, it will divide it in n-tiles
.
About the public static .call
method itself: first, we call method .find_by_sql
on model (in this case it's Post), and we just open quotes and write SQL.
What about the SQL? We specify which columns we want to retrieve, then we use the ntile(?)
with OVER
- this will be the criteria for ranking, visit_count exactly. We also have to use order by
, it is required for using ntile. There is also something called popularity
in here. I named it this way, but you can name it as you want. By this name, you will retrieve it’s ranking value, by calling it on instance of record (in my case, it’s post.popularity
)
And now, how do we know what popularity value (between 1 and 5) does each Post have? Simply call .popularity
on Post
instance retrieved by Query Object method.
How our controller will look like now? Simple:
tsx
With templates specified earlier, we see something like this when we visit our Posts#index

Of course you might want something prettier than plain number. With a little effort, you can change it to something cool, for example stars. I decided to add gem font-awesome-rails
for this article demo. With one small change in our partial file _post.html.erb
, like this:
tsx
I've achieved result like this:

Pros of this approach:
Clean and tidy
Fast-working (SQL window function is very efficient)
Quick to add
Little code
Cons: You tell me. Are there any?
Let’s Create a Great Website Together
We'll shape your web platform the way you win it!
More posts in this category
August 11, 2025 • 19 min read
READ MORELearn more about website development budget and timelineHow Much Does Website Development Cost and How Long Does It Take?
Planning a website development project can feel overwhelming, especially when you're trying to balance quality, functionality, and budget constraints. Understanding the real costs and timelines will help you make smart decisions and avoid expensive surprises.
July 30, 2025 • 19 min read
READ MORELearn more about checkout speed optimizationHow Fast Should Your Checkout Process Be for Maximum Conversions?
Imagine losing $2.5 million in annual revenue because of a single second. Sounds dramatic? If your online business generates $100 million yearly, a mere one-second delay in your checkout process could cost you exactly that much. This is neuroscience, backed by decades of research into how the human brain processes digital experiences.
July 07, 2025 • 18 min read
READ MORELearn more about modern website optimization for business growthModern Website Optimization for Business Growth
Countless businesses are leaving money on the table with websites that look pretty but don't perform. If you're wondering whether your website is actually driving growth or just taking up server space, you're not alone.