I am using rails 4.2, I just want to know if there would be any difference if I use the :foreign_key
keyword in my migrations rather than just adding a user_id
column to add relationship to my models ?
Asked
Active
Viewed 68 times
0

StormTrooper
- 65
- 8
-
Possible duplicate of [Does Rails need database-level constraints?](http://stackoverflow.com/questions/2589509/does-rails-need-database-level-constraints) – Michael Berkowski May 14 '16 at 12:52
1 Answers
4
YES
The key difference is not on the application layer but on the database layer - foreign keys are used to make the database enforce referential integrity.
Lets look at an example:
class User < ActiveRecord::Base
has_many :things
end
class Thing < ActiveRecord::Base
belongs_to :user
end
If we declare things.user_id
without a foreign key:
class CreateThings < ActiveRecord::Migration
def change
create_table :things do |t|
t.integer :user_id
t.timestamps null: false
end
end
end
ActiveRecord will happily allow us to orphan rows on the things table:
user = User.create(name: 'Max')
thing = user.things.create
user.destroy
thing.user.name # Boom! - 'undefined method :name for NilClass'
While if we had a foreign key the database would not allow us to destroy user
since it leaves an orphaned record.
class CreateThings < ActiveRecord::Migration
def change
create_table :things do |t|
t.belongs_to :user, index: true, foreign_key: true
t.timestamps null: false
end
end
end
user = User.create(name: 'Max')
thing = user.things.create
user.destroy # DB says hell no
While you can simply regulate this with callbacks having the DB enforce referential integrity is usually a good idea.
# using a callback to remove associated records first
class User < ActiveRecord::Base
has_many :things, dependent: :destroy
end

max
- 96,212
- 14
- 104
- 165
-
Make sure you index the foreign key column -- you probably would anyway, but with a foreign key declared in the database it would be wise to make sure that you do. There is a gem which helps with that ... don't remember the name ... – David Aldridge May 15 '16 at 22:59
-
I think you may be thinking of [foreigner](https://github.com/matthuhiggins/foreigner) however you don't need a gem to add foreign keys or indexes in a later migration - and it is done anyways if you use the `belongs_to` macro when declaring the column http://guides.rubyonrails.org/active_record_migrations.html#foreign-keys – max May 16 '16 at 10:39