Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding foreign key to a rails model

People also ask

Do you need foreign keys in Rails?

You do not need a foreign key constraints for ActiveRecord to correctly map the relationships. You can use validations to have the Rails app ensure data integrity.

What is a foreign key Ruby?

Foreign key relationships specify how tables relate to each other and indicate relationships between tables. RubyMine recognizes foreign key relationships in your database schema and uses them to construct JOIN clauses.

How do I remove a foreign key in Rails?

Rails provides add_foreign_key to add foreign key constraint for a column on a table. It also provides remove_foreign_key to remove the foreign key constraint. Before Rails 6, add_foreign_key and remove_foreign_key were not supported for SQLite3.


The currently accepted answer on this isn't really accurate as it doesn't add a database foreign key. It's just adding integer columns.

In Rails 4.2.x, the current approach is:

http://guides.rubyonrails.org/active_record_migrations.html#foreign-keys

Create a migration:

rails generate migration migration_name

For existing columns, in the migration add the foreign keys like this:

class MigrationName < ActiveRecord::Migration
  def change
    add_foreign_key :business_hours, :businesses
    add_foreign_key :businesses, :users
  end
end

For Rails 4.x or if you're adding a new column and want it to be a foreign key you can do this, where you probably also want to specify the index as true, but that's not part of the requirement for the foreign key:

http://edgeguides.rubyonrails.org/active_record_migrations.html#creating-a-migration

class MigrationName < ActiveRecord::Migration
  def change
    add_reference :business_hours, :business, index: true, foreign_key: true
    add_reference :businesses, :user, index: true, foreign_key: true
  end
end

First of all when you use belongs_to method don't use s at the end of the word: business_hours belongs_to business which belongs_to user.

Now create a migration:

rails generate migration migration_name

And in migration add columns:

class MigrationName < ActiveRecord::Migration
  def change
    add_foreign_key :business_hours, :businesses
    add_foreign_key :businesses, :users
  end
end

Run rake db:migrate. That's it.


Rails 5 now can add foreign key in migrations, see http://devdocs.io/rails~5.0/activerecord/connectionadapters/schemastatements#method-i-add_foreign_key. So

 add_foreign_key :articles, :authors

creates

 ALTER TABLE "articles" ADD CONSTRAINT fk_rails_e74ce85cbc FOREIGN KEY ("author_id") REFERENCES "authors" ("id")

If you have a non standard data model you can do.

 add_foreign_key :articles, :users, column: :author_id, primary_key: "lng_id"

which creates

 ALTER TABLE "articles" ADD CONSTRAINT fk_rails_58ca3d3a82 FOREIGN KEY ("author_id") REFERENCES "users" ("lng_id")

I haven't tried it with PostgreSQL but at least with MySQL Rails do NOT create foreign keys, I mean not real db-level foreign keys. All they create is an integer that is named according to the convention. That means that out of the box you do not get the index on this fake foreign key(for faster lookup) and there is also no db-level referential integrity check. To get that you need to do something like:

ALTER TABLE your_table ADD CONSTRAINT fk_whatever_you_want_to_name_it FOREIGN KEY   (foreign_key_name) REFERENCES another_table(its_primary_key)

In a Rails migration you can pass this as a string argument to the "execute" function. Adding a "real" foreign key also automatically creates an index. At least for me this was a rather nasty surprise.