I recently made an app with a React JS frontend and a Rails API backend. I needed to make a schedule of games. That sounded simple, but when I started building out the API setup I quickly realized it was not simple at all. There are a few tricks you can use when setting up an API for a game schedule that I think you will find very useful.
First off my thought was a TEAM has many GAMES and a GAME belongs to a team. That is what most logical people would think. This is true to a certain extent but the problem is that a GAME has TWO TEAMS. So this code does NOT fulfill the requirements of an API for a schedule of games.
Class Team < ApplicationRecord
has_many :games
end
Class Game < Application Record
belongs_to :team
end
This will not work because technically a GAME is going to have more than one TEAM.
My first INCORRECT solution - I figured this is a case for a join table. I began to brainstorm how I would put a new model called schedule and join the teams and games together. The more I thought about this the more I thought this might work but doesn't seem to be the right way to go about this. Since a game will have two teams and two teams only I thought there had to be a better way than creating a join table for the two models.
My second INCORRECT solution - Then it dawned on me each GAME will have a HOME TEAM and an AWAY TEAM so I could just make two TEAM models one for home and one for away. This would definitely work because now you would have two has_many and belongs_to relationships which would work for a schedule. Here was the problem that I saw, say you have TEAM Rollers.
You will have to create two TEAMS for the Rollers an AWAY TEAM and a HOME TEAM. This is doable but then what do you do when you want to take stats for the Rollers. You are going to have to add together both teams just to find something simple like their wins and losses.
Final Solution - Here is what I decided to use for my API. Instead of creating two separate models for an AWAY TEAM and a HOME TEAM, when writing out the models I aliased a home_team and an away_team with the class name of "TEAM". For the TEAM model it was similar has_many home_games with a class name of "GAME" and the same was done for away games.
class Game < ApplicationRecord
belongs_to :home_team, :class_name => "Team"
belongs_to :away_team, :class_name => "Team"
end
class Team < ApplicationRecord
has_many :home_games, :class_name => "Game", :foreign_key => 'home_team_id'
has_many :away_games, :class_name => "Game", :foreign_key => 'away_team_id'
end
What this will allow you to do is create a schedule that has a home_team and an away_team. When you go into a team to access their home or away games active record has given you this method. Rollers.home_games, this will give you a list of home games that the Rollers have either participated in or are scheduled to play in.
You may be thinking: Ok well how are you going to find the stats of each team. Won't you have to combine home_team and away_team anyways. Does that really solve the problem that you had before???
I think it helps immensely, what this allowed me to do was handle everything in my backend by writing some methods for each model. If it wasn't set up this way it would need to be handled on the frontend which would be no good if you were to ask me. Here is an example of calculating wins for a team.
def wins
games = self.away_games + self.home_games
games.collect.count do |x|
if x.winner
x.winner[:name] == self.name
end
end
end
Combining the games in the backend like this at the top is super easy. Now all I had to do was a simple if statement to see if this team was the winner. This will come through on the API as wins and there is another method I have very similar called losses.
All this calculation will be done when my fetch request is made so it won't slow down my application on the frontend every time I load the team page that shows their wins and losses.
This is the best way to set up a schedule and has worked for me. I hope that you enjoy this and give it a try if this is something similar to what you build in the future.
Top comments (0)