Previous versions of Rails did not have the ability to create foreign keys without resorting to executing SQL statements directly. This lead to messy, database dependent solutions that weren't very nice. Luckily, Rails 4.2 rectifies this with new features to add and remove foreign keys. In this article we will discuss what foreign keys are, and how to add them to your database.

Rails Version 4.2+
Other Notes New feature introduced in Rails 4.2.

If you don't know what a foreign key is, well, quite simply, a foreign key links one table to another's primary key. For example, if I have an authors table and a books table, I could create a foreign key that points from books back to authors, thereby linking the two tables together. Then, these two tables become linked. This means that I cannot add or update the record with invalid data for the author_id field in the books table. I can also tell the database server what to do when I update or delete the record. For example, I can tell rails to automatically delete child records when the parent is deleted (delete an author from the authors table and all the author's books are deleted). I could also tell Rails to set the author_id column to null or to simply not let me delete the author while child records exist.

Adding Foreign Keys

To add a foreign key to the books table, we simply do:

add_foreign_key :books, :authors

We can also give the foreign key a custom name (Rails automatically names the foreign key otherwise):

add_foreign_key :books, :authors, name: :my_foreign_key

If we are using a non Rails friendly database, we can specify the column names we wish to use for the foreign key. For example, let's say the primary key of the authors table is author_id and the key in the books table is aid. We could simply use the following code to create the foreign key:

add_foreign_key :books, :authors, column:  :aid, primary_key: :author_id

We can control the behavior of the foreign key as well. A list of the available behaviors are below. Independent behaviors can be set for both update as well as delete.

  • :restrict (default) - Prevents changes from being made.
  • :nullify - Sets the child columns to null.
  • :cascade - Cascades down to the child records. For instance, deleting an author deletes the author's books.

To specify behaviors, you simply use the on_delete or on_update parameters. For example, the following code would cascade deletes so that the books get deleted when the parent gets deleted.

add_foreign_key :books, :authors, on_delete: cascade

Deleting Foreign Keys

It is just as easy to delete foreign keys:

remove_foreign_key :books, :authors

You can optionally specify the name of the foreign key to delete:

remove_foreign_key :books, name: :my_foreign_key

If you have non Rails friendly column names, you can specify the column name that contains the foreign key you wish to remove.

remove_foreign_key :books, column: :aid

That's it! Thanks for reading!