views:

99

answers:

2

Rails has no way of creating foreign keys in migrations (there are plugins to do this, however). There are also plenty of cascading options so you can get cascading deletes, for example.

With all of these options built in, is it worth creating foreign keys in the database? Is this something Rails developers normally avoid or what? You'd think if it was a recommended practice that Rails would natively support it.

+4  A: 

This is something of a holy issue, because DHH (the creator of Rails) has stated before that he sees the database as essentially a giant hash table, so taking advantage of some of the things that database engines are good at by using features such as constraints or stored procedures is not considered The Rails Way by Rails purists.

That said, if you'd like to enforce the integrity of your data closest to the data, or if your database is shared by other applications then by all means use one of those plugins to create the foreign keys. After all, what harm could it do, right?

John Topley
Sounds like rails is going to be the downfall of good database use :p
ryeguy
@ryeguy The Internet is the downfall of good database use. Read up on NoSQL :p
meagar
+4  A: 

Rails doesn't prevent you from using foreign key constraints in your database, it just doesn't give them to you by default. The "Rails Way" is to depend on Rails to manage your database, cascade your deletes, enforce referential integrity, etc.

There are several plugins to add foreign key constraints to your migrations, but I usually opt to add them manually. Assuming you've created CreateUsers and CreatePosts migrations, you could add a "LinkPostsToUsers" migration:

# Assumes PostgreSQL
class LinkPostsToUsers < ActiveRecord::Migration
  def self.up
    execute "
      ALTER TABLE posts 
        ADD CONSTRAINT fk_posts_user_id
        FOREIGN KEY (user_id) REFERENCES users(id)
        ON DELETE CASCADE
        ON UPDATE CASCADE"
  end

  def self.down
    execute "ALTER TABLE posts DROP CONSTRAINT fk_posts_user_id"
  end
end
meagar
You misspelled "REFERENCES" word.
Dmitry