DEV Community

Cover image for Use a particular column as a foreign key in rails
Masroor Hussain
Masroor Hussain

Posted on • Updated on

Use a particular column as a foreign key in rails

In rails, to add a foreign key, we usually do

rails generate migration AddReferenceToXX mm:references
Enter fullscreen mode Exit fullscreen mode

what this does is that it adds a foreign key to the XX table, and uses the mm model's attribute id as the referenced column. However, this id is not what we'd always want to use as a foreign key, what if we want to use some other column as a foreign key, let's say the column email? In this article, we're going to learn exactly that thing.

Suppose we have two models named GmailInbox and GmailThread, their relationship being that GmailInbox has many GmailThreads and a GmailThread belongs to only one GmailInbox, so it's a One-to-Many relationship.

We need a way to connect the GmailThread to a GmailInbox based on the email (because a Gmail account is identified based on the email)
GmailInbox: id, email
where email attribute will have a uniqueness constraint (i.e no duplicates allowed in this column since it is going to be a referenced column for a foreign key).
GmailThread: id, thread_id, inbox_email
we will use inbox_email attribute as a foreign key to refer to the Gmail inbox it belongs to.

Firstly, we will generate a migration, using

rails generate migration add_foreign_key_to_gmail_threads
Enter fullscreen mode Exit fullscreen mode

Then we need to add uniqueness constraint on the column of the referenced table, after that, we'll add the foreign key to the gmail_threads table.

our migration file will be

def change
  add_index :gmail_inboxes, :email, unique: true
  add_foreign_key :gmail_threads, :gmail_inboxes, column: :inbox_email, primary_key: :email
end
Enter fullscreen mode Exit fullscreen mode

the syntax explanation is

add_index :table_name, :column_name, unique: true

add_foreign_key :from_table, :to_table, column: :foreign_key_column, primary_key: :referenced_column

The last thing we need to do is to put the foreign key information in our models.

class GmailThread < ApplicationRecord
  belongs_to :gmail_inbox, foreign_key: 'inbox_email', primary_key: 'email', optional: true
end
Enter fullscreen mode Exit fullscreen mode

and do the same in GmailInbox model

class GmailInbox < ApplicationRecord
  has_many :gmail_threads, foreign_key: 'inbox_email', primary_key: 'email'
end
Enter fullscreen mode Exit fullscreen mode

and that's it.

Oldest comments (2)

Collapse
 
dandyandy22 profile image
Andras Mihaly

Really appreciated the breakdown, thanks.

Collapse
 
masroorhussainv profile image
Masroor Hussain

glad that it helped!