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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With