Creating a custom name for a foreign key
Tags: rails, ruby
Published: 2020-07-16 18:41:25

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.

```terminal 
rails g resource game home_team:references away_team:references
```  

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]
  def change
    create_table :games do |t|
      t.references :home_team, null: false, foreign_key: true
      t.references :away_team, null: false, foreign_key: true
      t.references :season, null: false, foreign_key: true
    end
  end
end
](https://dev-to-uploads.s3.amazonaws.com/i/n5uysaigrc6edbj0sasq.png)

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: 

```ruby 
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
```
___

### Model
![Model file. Text: class Game < ApplicationRecord
  belongs_to :season
  belongs_to :home_team
  belongs_to :away_team
end
](https://dev-to-uploads.s3.amazonaws.com/i/lmq0ynd3li26y2l093bn.png)

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.

```ruby 
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
``` 
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"> 
```