DEV Community

Cover image for Creating a custom name for a foreign key
Joe Avila
Joe Avila

Posted on • Edited on

Creating a custom name for a foreign key

My local basketball league is currently using free software that has shortcomings and is littered with ads. So I'm working on a site where we can upload our game statistics, and is catered to us. It will have more functionality than our current site, no ads, and as a new basketball player I can track my growth. This article is going to dive into creating a customized associations in Rails that will streamline functionality for when I want to display games stats on the frontend.

I have a reference table called games that tracks two teams in my database, the home team and the away team. By keeping this relationship on one table I can make calls to the Game table and find out who the winner was.

 rails g resource game home_team:references away_team:references 
Enter fullscreen mode Exit fullscreen mode

I'll start by running a generator for games. This will create my model, migration, and controller. I will only focus on the migration and model files as that's where our changes will need to happen. I don't have models called Home Team or Away Team (they are just a Team), so I need to tell Rails what those are and where to look.

Migration

Migration file. Text: class CreateGames < ActiveRecord::Migration[6.0]<br> def change<br> create_table :games do |t|<br> t.references :home_team, null: false, foreign_key: true<br> t.references :away_team, null: false, foreign_key: true<br> t.references :season, null: false, foreign_key: true<br> end<br> end<br> end<br>

In our generated migration file I need to change the ends of line 4 and 5. Here I am telling Rails: these columns are foreign keys of a table with a different name. Home Team and Away Team both point to the Teams table. The new code will be:

 class CreateGames < ActiveRecord::Migration[6.0] def change create_table :games do |t| t.references :home_team, null: false, foreign_key: {to_table: :teams} t.references :away_team, null: false, foreign_key: {to_table: :teams} t.references :season, null: false, foreign_key: true t.timestamps end end end 
Enter fullscreen mode Exit fullscreen mode

Model

Model file. Text: class Game < ApplicationRecord<br> belongs_to :season<br> belongs_to :home_team<br> belongs_to :away_team<br> end<br>

I need our game model to belong to two teams. This has some conflicts with Active Records base functionality. Inherently belongs_to is a one-to-one connection. I need to change some code here.

 class Game < ApplicationRecord belongs_to :season belongs_to :home_team, class_name: 'Team', foreign_key: 'home_team_id', required: true belongs_to :away_team, class_name: 'Team', foreign_key: 'away_team_id', required: true end 
Enter fullscreen mode Exit fullscreen mode

Essentially I am creating an alias. Home Team is actually just a Team, and Away Team is a different Team. This allows me to work around the one-to-one connection of belongs_to while achieving desired functionality.


Voila! I am now able to go into my rails console and create some test data.

 hTeam = Team.create(name: "Bears") aTeam = Team.create(name: "Aces") g = Game.create(away_team_id: aTeam.id, home_team_id: hTeam.id) g.home_team #=> <Team id: 1, name: "Bears", created_at: "2020-06-01 17:41:14", updated_at: "2020-06-01 17:41:14"> g.away_team #=> <Team id: 2, name: "Aces", created_at: "2020-06-01 17:42:14", updated_at: "2020-06-01 17:42:14"> 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)