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
Suppose we have two models named
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
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
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!