Does rails enforce referential integrity?

Hi,

Is rails supposed to support referential integrity? That is rails
either support to be able to ensure that when a new contact is created
this can only happen if a valid suberb is associated with it, and which
mechanisms of the below are supposed to do this?
(a) using DB foreign key constraints information as a basis?
(b) using the “has_one” line in the model file to enfore?

If neither of these are enforced what is the best way to enforce this
integrity?


class Contact < ActiveRecord::Base
has_one :suberb
end

class Suberb < ActiveRecord::Base
belongs_to :contacts
end

class CreateSuberbs < ActiveRecord::Migration
def self.up
create_table :suberbs do |t|
t.column :contact_id, :integer
t.column :name, :string
t.column :postcode, :integer
end
execute “alter table suberbs
add constraint fk_suberb_contacts
foreign key (contact_id) references contacts(id)”
end

def self.down
drop_table :suberbs
end
end

Tks

Greg H. wrote:

Hi,

Is rails supposed to support referential integrity? That is rails
either support to be able to ensure that when a new contact is created
this can only happen if a valid suberb is associated with it, and which
mechanisms of the below are supposed to do this?
(a) using DB foreign key constraints information as a basis?
(b) using the “has_one” line in the model file to enfore?

Skip the db constrains and use Rails validations to achive referential
integrity:


class Contact < ActiveRecord::Base
has_one :suberb
end

class Suberb < ActiveRecord::Base
belongs_to :contact
validates_presence_of :contact_id
validates_associated :contact
end

Cheers,
Bragi

Łukasz Piestrzeniewicz wrote:

Skip the db constrains and use Rails validations to achive
referential
integrity:

This may indeed be the correct answer to the OP’s question but you
realize that by not building RI into the data model, you’re making it
somewhat more difficult to re-use this database for other applications.
(At minimum, another application will need to code the same RI
constraints and you will need to transmit this knowledge outside of the
data model.) Generally speaking, is that all right with you?

It’s clear that RoR favors a style in which the data are defined along
with the application- that’s a clear bias of the framework- but are we
also saying that databases are to be considered purpose-build components
for specific applications? Just curious what people’s opinions are.

Łukasz Piestrzeniewicz wrote:

Greg H. wrote:

Hi,

Is rails supposed to support referential integrity? That is rails
either support to be able to ensure that when a new contact is created
this can only happen if a valid suberb is associated with it, and which
mechanisms of the below are supposed to do this?
(a) using DB foreign key constraints information as a basis?
(b) using the “has_one” line in the model file to enfore?

Skip the db constrains and use Rails validations to achive referential
integrity:


class Contact < ActiveRecord::Base
has_one :suberb
end

class Suberb < ActiveRecord::Base
belongs_to :contact
validates_presence_of :contact_id
validates_associated :contact
end

Cheers,
Bragi

I was wondering something related to this question. With foreign keys in
PostgreSQL, if I update an ID for a table, it will update all related
IDs for other tables associated with it. Is something like this possible
for rails?

Francis C. wrote:

Łukasz Piestrzeniewicz wrote:

Skip the db constrains and use Rails validations to achive
referential
integrity:

This may indeed be the correct answer to the OP’s question but you
realize that by not building RI into the data model, you’re making it
somewhat more difficult to re-use this database for other applications.
(At minimum, another application will need to code the same RI
constraints and you will need to transmit this knowledge outside of the
data model.) Generally speaking, is that all right with you?

It’s clear that RoR favors a style in which the data are defined along
with the application- that’s a clear bias of the framework- but are we
also saying that databases are to be considered purpose-build components
for specific applications? Just curious what people’s opinions are.

I am a very simple man. I learned about encapsulation and I use it
successfully. Encapsulation is about not exposing internal data.
Application is an object so it also must obey encapsulation. If you want
two applications to share data then one of them must be responsible for
storage. The other one can access only the API that the first one
exposes. You have several options and REST webservices are probably the
most simple to implement.

Databases are awful at being more than just a storage engine. If it
would be possible to use database to enforce complicated business rules
in simple, fast and easy to maintain way, we would not need ActiveRecord
in the first place.

The best thing is to forget about all those ‘features’ that database
manufacturers advertise and use databases for the only purpose they were
created: to store data.

Once you stop thinking in salesman categories you will see the light :wink:

Cheers,
Bragi

Rick Martinez wrote:

I was wondering something related to this question. With foreign keys in
PostgreSQL, if I update an ID for a table, it will update all related
IDs for other tables associated with it. Is something like this possible
for rails?

Wow. ID is The Identity. It’s not the name or nick. It’s the very
essence of being. Why would you like to change that?! I for example
would be very mad if you would try to change my identity just to fool
all my aquintances! You are trying to do something very very bad.

No. Luckly Rails does not allow such mischief. If you want to exchange
one object with another you have to manually go to his every pal and
say: I no longer like this old object and I want you to use this shiny
new one instead. Which is a good thing because if you try to give them
something they do not like they will, nomen omen, object.

This gives your application a lot better protection than referential
integrity.

Cheers,
Bragi

Łukasz Piestrzeniewicz wrote:

I am a very simple man. I learned about encapsulation and I use it
successfully. Encapsulation is about not exposing internal data.
Application is an object so it also must obey encapsulation. If you want
two applications to share data then one of them must be responsible for
storage. The other one can access only the API that the first one
exposes. You have several options and REST webservices are probably the
most simple to implement.

Well, one attractive thing about your point of view is that many people
agree with you. I’ve seen big companies with fifty different customer
databases and several hundred personnel directories, most of them with
essentially the same information in them. I guess the enlightened way to
look at that would be “encapsulation” rather than “integration hell.”

One of my concerns with Rails is that it encourages thinking like yours,
at the expense of proper data modeling (which you dismiss as “just
storage”). After a few more years of growth and success for Rails,
people may find that they have a lot of Rails applications that can’t
work together. That may or may not be a problem.

On 8/13/06, Łukasz Piestrzeniewicz [email protected] wrote:

Skip the db constrains and use Rails validations to achive referential
validates_associated :contact

end

I’d use db constraints as well. Or only db constraints if rails’
validations turn out to be a bottleneck (profile!).

Isak

On Aug 13, 2006, at 7:46 AM, Francis C. wrote:

It’s clear that RoR favors a style in which the data are defined along
with the application- that’s a clear bias of the framework- but are we
also saying that databases are to be considered purpose-build
components
for specific applications? Just curious what people’s opinions are.

The “Rails Way” made me very nervous at first. I was a strict DB
authoritarian,
and felt that the DB should be tight as a drum.

But, after using Rails, and listening to the community, I think
there’s a LOT
to be said for keeping DB’s application specific, and opening up web
services
to allow other applications to gain DB access.

Once the web services are in place, you loose the concerns of DB
locality and
platform-driver availability. Your DB design is encapsulated,
allowing for DB
re-factoring without recriminations. :slight_smile:

Yes, there are performance concerns. What’s new? Each level of
abstration
brings performance hits, but the advantages keep outweighing the
disadvantages
or we wouldn’t keep moving up that ladder.

Just my humble opinion, your mileage may very.


– Tom M.

Francis C. wrote:

constraints and you will need to transmit this knowledge outside of the
data model.) Generally speaking, is that all right with you?

It’s clear that RoR favors a style in which the data are defined along
with the application- that’s a clear bias of the framework- but are we
also saying that databases are to be considered purpose-build components
for specific applications? Just curious what people’s opinions are.

For why RoR is like it is, see David Heinemeier H.'s blog post,
“Choose a single layer of cleverness”:

http://www.loudthinking.com/arc/000516.html

in which he says:

Christopher Petrilli voices a frequent misconception about Active Record, the ORM of Rails, in Least common denominator. The thinking goes that MySQL is holding us back from taking advantage of more advanced database features available in PostgreSQL, Oracle, and others. That if only MySQL was more clever, had more features, we would be embracing them with open arms. Wrong.

Active Record is opinionated software, just like the rest of Rails. This
is a matter of opinion, not constraints. And the opinion goes as
follows: I don’t want my database to be clever! Keep those crayons
firmly in place, please.

Unlike Christopher, I consider stored procedures and constraints vile
and reckless destroyers of coherence. No, Mr. Database, you can not have
my business logic. Your procedural ambitions will bear no fruit and
you’ll have to pry that logic from my dead, cold object-oriented hands.

Before the DBA-induced side of your brain explodes at that statement,
please do read Martin F.'s article on the difference between
application and integration databases. And realize that my opinions are
confined to dealing with application databases (and that doing
integration through the database belongs in a time where Beverly Hills
90210 was a hit show on TV). Hopefully that calmed you down again.

In other words, I want a single layer of cleverness: My domain model.
Object-orientation is all about encapsulating clever. Letting it sieve
half ways through to the database is a terrible violation of those fine
intentions. And I want no part of it.

All that being said: Whatever floats your boat. Active Record is
surprisingly forgiving of your transgressions if you choose to hang out
at the Peach Pit. As long as you’re not banking your savings on a hope
we’ll change our ways once MySQL “grows up” and adds all these
Enterprise Features to become something bigger and better than a “toy
project”. You’ll die poor, then, I tell you.

The Martin F. article he refers to is here:

Having said that, very many Rails users (including Dave T. [1])
value having referential integrity enforced at DB level, and it is
usually the case that DHH is happy for others to extend Rails (via
plugins) to cover uses he isn’t personally interested in.

regards

Justin

[1] In a footnote in the second edition of AWDR Dave T. writes:

"Many Rails developers donâ??t bother specifying database-level
constraints such as foreign keys, relying instead on the application
code to make sure that everything knits together correctly. Thatâ??s
probably why Rails migrations donâ??t let you specify constraints.
However, when it comes to database integrity, I (Dave) feel that an
ounce of extra checking can save pounds of late-night production system
debugging. You can find a plugin that automatically adds foreign key
constraints at http://www.redhillconsulting.com.au/rails_plugins.html.

Łukasz Piestrzeniewicz wrote:

The best thing is to forget about all those ‘features’ that database
manufacturers advertise and use databases for the only purpose they were
created: to store data.

HARD DISKS were created for the purpose of storing data. RELATIONAL
DATABASES
were created for the purpose of managing data.