DEV Community

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

Posted on • Edited on

14 2

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

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay