Depot Application Tutorial and Foreign Keys

I’ve been working my way through the depot application tutorial in the
Agile Rails book, and I’m at the “Check Out!” chapter. In the migration
file for the line items, there are SQL commands to create foreign keys.
Up until this point I have been using SQLite3, which as far as I’m aware
doesn’t support these functions. However, after briefly scanning through
the rest of the chapter, it seemed to me that these links between
database tables are handled in the model files, with has_many and
belongs_to, so I ploughed on regardless.

Having got to the end of the chapter with everything working as
described in the book, I am wondering if there really is any need to set
up foreign keys in the database. Is it just “good practice” when
designing database schemas? And does the Ruby code handle this
functionality satisfactorily without foreign keys?

Please excuse me for my ignorance regarding databases - I’m not a web
developer by trade, I’m a Structural Engineer - but I’d like to gain a
greater understanding of the core principals concerning Rails.

Your associations, validations, and callbacks emulate foreign keys so
there’s no reason to define them in terms of data constraints.

class Foo < ActiveRecord::Base
belongs_to :bar
validates_presence_of :foo_id
validates_associated :foo
end

class Bar < ActiveRecord::Base
has_many :foos, :dependent => :destroy
end

You can add indexes via a migration.

However, one thing that foreign keys give you is an index on that
column.
So if you don’t declare them as foreign keys (which I don’t) then you
should
declare an index on those columns to help with lookups.

Brian H. wrote:

Your associations, validations, and callbacks emulate foreign keys so
there’s no reason to define them in terms of data constraints.

[snip]

However, one thing that foreign keys give you is an index on that
column.
So if you don’t declare them as foreign keys (which I don’t) then you
should
declare an index on those columns to help with lookups.

Thank you for the explanation.

Is there a situation where creating foreign keys, as opposed to indices,
would be required? Say, if you wanted the database to be used by other
(non-Rails) applications or administration tools?

Of course. But you get into that sticky situation of moving business
logic
into your database. This is one reason SOA is becoming so popular…
make
application A use application B to control the database rather than
going to
it directly.

You’ll touch off a holy war here if you’re not careful :slight_smile: The main
point is
that Rails does not need nor require them, and you may get unexpected
results if, for example, your database has constraints of the foreign
key
that restricts its input but you have not handled that in the models, or
perhaps you cascade-delete records on your database and you don’t deal
with
that in your apps.

In short, it’s all up to you. There are ways to handle all of those
concerns; if you need to use FKs, by all means do so.

Brian H. wrote:

In short, it’s all up to you. There are ways to handle all of those
concerns; if you need to use FKs, by all means do so.

I’m happy to steer clear of them, seeing as I don’t really know anything
about them :wink: I was just curious as to whether a Rails app would
benefit from them or not.

Thanks again for your explanation.