In rails, to add a foreign key, we usually do
rails generate migration AddReferenceToXX mm:references
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 GmailThread
s 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
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
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
and do the same in GmailInbox
model
class GmailInbox < ApplicationRecord
has_many :gmail_threads, foreign_key: 'inbox_email', primary_key: 'email'
end
and that's it.
Top comments (2)
Really appreciated the breakdown, thanks.
glad that it helped!