Why do Rails migrations define foreign keys in the application but not in the database?

eggdrop picture eggdrop · May 30, 2009 · Viewed 11.9k times · Source

If I define a Customer and Order model in which a Customer "has many" Orders and the Order "belongs to" the Customer, in Rails we talk about Order having a foreign key to the Customer through customer_id but we don't mean that this is enforced in the database.

Because Rails does not define this as a database-level constraint, there is a risk of your data's integrity being violated, perhaps outside the application (or inside if you receive simultaneous requests?), unless you enforce the constraint in the database manually.

Why does Rails not define the foreign key at the database level or is there a way to get Rails to do this?

class Customer < ActiveRecord::Base
  has_many :orders
end

class Order < ActiveRecord::Base
    belongs_to :customer
end

ActiveRecord::Schema.define(:version => 1) do

  create_table "customers", :force => true do |t|
    t.string   "name"
  end

  create_table "orders", :force => true do |t|
    t.string   "item_name"
    t.integer  "customer_id"
  end

end

Answer

Bill Karwin picture Bill Karwin · May 30, 2009

Rails holds some conventions that enforcement of data integrity should be done in the application, not in the database.

For example, Rails even supports some database designs that cannot use foreign keys, such as Polymorphic Associations.

Basically, Rails conventions have treated the database as a static data storage device, not an active RDBMS. Rails 2.0 is finally supporting some more realistic features of SQL databases. It's no surprise that the result will be that developing with Rails will become more complex than it was in version 1.0.