Building a Recommendation Algorithm in Ruby on Rails (Part 1)
By: Sean Laflam
Tags: Recommendation System, Ruby on Rails, Ruby, Algorithms, Cosine Similarity

Using Ruby’s Vector class, and some custom Rails methods

The Types of Recommendation Systems

There are 2 widely used systems to recommend products to customers, whether that product be physical goods like Amazon sells, television shows or movies like Netflix, or even other user’s profile pages like Facebook.

Collaborative Filtering

Collaborative filtering compares the likes, dislikes, and trends of user’s to match them with other similar users, and then recommend them products based on what the other similar user’s enjoy. For example, if User A watches a bunch of the same Rom-Coms on Netflix as User B, and both users rate them similarly, if User A finds a new show they like, it will then be recommended to User B. This approach has advantages as it allows the system to recommend things to the user that may be completely outside of their normal likes or behavior. The disadvantage, however, is that it requires many users and many ratings for each user in order to build an effective system.

Content-Based Filtering

Content-Based filtering uses the traits of one product, to associate it with other similar products in order to make recommendations to users. This is the much simpler system to use for sites or applications without many users at the beginning as it lets you make recommendations without needing a ton of data on other user’s behavior. This is the system we will be using for the purpose of this article today.

Building the Algorithm

In order to build this algorithm we will begin by setting up a Ruby on Rails Application, and seeding it with some products we’d like to make recommendations for. For our example today, I will be using board games as the product, with data pulled from the Board Game Atlas API.

Board Game Atlas provides tons of information on each game, which we will use to create attributes for each.

In order to access the API information, head to this link and register for an account. One set up, you’ll see something like this:

Now, what you’re going to want to do is make a query to the endpoint at https://api.boardgameatlas.com/api requesting the board games based on some criteria. In this example we will be requesting the 100 most popular games by using the following URL paramaters:

https://api.boardgameatlas.com/api/search?order_by=popularity&ascending=true&client_id=[YOUR_CLIENT_ID_HERE]

This will return an array of game objects in JSON format sorted by most popular in order from 1 to 100.

Storing the data from the API in your Ruby backend

For simplicity, we’re going to use a Ruby gem called Rest Client to perform the request to the API endpoint detailed in the last section.

First, add the gem to your gemfile by typing ‘bundle add rest-client’ into your terminal, or by adding it into the gemfile manually.

Next, you need to require Rest Client at the top of your seeds.rb file like so:

require ‘rest-client’

Still in the seeds file, we will make the get request to the Board Game Atlas endpoint using Rest Client, and store the return value in a variable we’ll call games_array:

games_array = RestClient.get('https://api.boardgameatlas.com/api/search?client_id=Af1TZudirh')

Your response will look something like this:

A hash/object with an array inside of it called games. Each array has a ton of information about each game, but for our purposes we really only need the name, the image, the price, and the number of players.

Iterating through games_arry to create instances of the Game class

Now before this next step, you’re going to want to make sure you have a model and controller set up in your Rails application called ‘Games’. The quickest way to do that is by using ‘rails g resource Game’ to set up all of the necessary components. For more info on this step, read this blog post.

Assuming you have the model and controller for game setup, we’re going add the following code to our seeds.rb file:

games_array.each do |game| Game.create( name: game[:name], image: game[:image], price: game[:price], max_players: game[:max_players], min_players: game[:min_players], board_score: rand(10), players_score: rand(10), card_score: rand(10), party_score: rand(10), ) end

Now what this will do is create 100 instances of our Game class and it will assign each random values from 0 to 9 for four attributes called “board_score”, “players_score”, “card_score”, and “party_score”. These are attributes I’ve created for this exercise, and they represent how much of a board game element there is to the game, how much a card-based element, if the game is good for party settings, and how many players can play the game.

If we were doing this for a real application, the only way to get accurate recommendations is to go through each and create these rankings appropriately rather than at random, but since we are focusing on building the actual algorithm in this blog, rather than making accurate recommendations for board games, a random number will work fine for our purposes.

Once this step is complete, we can run ‘rails db:seed’ in the terminal, open up the console with ‘rails c’ and then type Game.all to see all of our Game instances.

At this point we are about halfway done with building out the algorithm in the backend. When you’re ready you can find the 2nd part of this tutorial here where we actually build the algorithm.

Cheers!

-Sean