Active Record design seems awkward and possibly broken

You can still achieve reuse and normalization at the object layer -
create a class “Address” and embed this within the Student and School
classes using composite objects (composed_of). This ensures that all
addresses have the same format. To edit addresses in a generic fashion
(“click to edit address”) you could create an address editor
(controller) that receives the name of the parent class and the record
id. Address validation is provided by a validate method on the Address
class. Or include the address fields within the parent form using a
partial page template.

IMHO collecting all the addresses for all the domain objects into a
single address table is a little over-zealous. It is like taking a
storefront application and extracting all the pricing information
(currency, dollars and cents) into a single price table. Prices should
remain with the items, whether they are catalog items, cart items, order
items, or invoice items. But this is a matter of taste…

I’m with dom. the solution you seem to want is Multi Table inheritances.
I say solution but it seems inacrurate as you lac an actual problem. the
removal of a school should not trigger the removal of an address as the
building may have been converted to offices(unlikely but possible) in
which case the address is still valid. It would seem to me that the
problem if there is one is in your inflexable database design not the
rails frame work. The one to one relationship of an address to a
structure is one used as example in a book I’ve been reviewing which
makes this same point. You have given no reason as to why you have
separated out the address. Meaning that this is not a good database
design as it is costing an extra two integers of memory capacity per
school.

Graham G. [email protected] <graham.glas wrote:

For example, if I want to keep a separate addresses table so that, say,
both schools and students could maintain addresses using the same
address schema,

This is a classic case of over-normalizing. There’s, what, 8 fields in
the address schema? Do you really need to go to all the trouble of
maintaining two new relationships and a whole separate table to keep
from putting those 8 fields in both tables?

On top of that, by using a separate table for the address, you’re adding
complexity to any and all database operations that involve addresses.
Where a single table approach could look up a school by address in one
super simple query, a two table approach would require an :include
directive and a lot of LEFT JOIN black magic behind the scenes. To
reiterate, this doesn’t even gain you any particular benefits.

Finally, you seem very resistant to changing your database schema to
work with the Rails conventions. However, did you ever stop to think
that the reason those conventions exist in the first place (and don’t
appear to support your use case) is because your use case is incorrect?
I don’t mean to sound offensive, but I think this is the case.

I think it’s pretty dangerous to go down the road of suggesting that
someone is over-normalizing without fully understanding their
application, or even worse, to suggest that ActiveRecord is good enough
for all schemas, and if not then the schema is the problem.

Bryan D. wrote:

This is a classic case of over-normalizing. There’s, what, 8 fields in
the address schema? Do you really need to go to all the trouble of
maintaining two new relationships and a whole separate table to keep
from putting those 8 fields in both tables?

That really depends on the application.

On top of that, by using a separate table for the address, you’re adding
complexity to any and all database operations that involve addresses.
Where a single table approach could look up a school by address in one
super simple query, a two table approach would require an :include
directive and a lot of LEFT JOIN black magic behind the scenes. To
reiterate, this doesn’t even gain you any particular benefits.

What if you want to look up all entities with a certain address? What
if the zipcode changes for the address? Sure this schema is more
complex, but it also contains more information. The extra joins are
just the cost of the extra information. Whether or not the cost is
justified depends on whether that information is necessary. If it is,
then de-normalizing has higher costs both in terms of query complexity
as well as data maintenance the risk of corruption.

In this case I would tend to agree with you, but don’t say there are no
benefits. It’s a legitimate choice.

Finally, you seem very resistant to changing your database schema to
work with the Rails conventions. However, did you ever stop to think
that the reason those conventions exist in the first place (and don’t
appear to support your use case) is because your use case is incorrect?
I don’t mean to sound offensive, but I think this is the case.

On one hand, fudging your schema a little bit to work better with
ActiveRecord is a calculated sacrifice that may well be worth it. On
the other hand, adopting a worldview that your schema must conform to
the capabilities of AR will result in a dangerous dumbing down of your
data modeling skills. All ORM is inherently flawed because relational
databases have far far richer semantics for data definition than
objects. ActiveRecord is nice because it makes the easy things easy,
but it would be folly to think that the hard things can magically be
made easy by ignoring their necessity.

All that said, I think the original poster is wrong to criticize the
semantics of belongs_to. It’s intuitive for most cases. The confusion
arises from the imprecise human language semantics of ownership. But at
the end of the day you have to know what it means at the database level.
He’s wrong to say he “wants AR to support good relational database
design”, because it fully supports his use case, just not the way he
imagined it would. Problem is there are millions and millions of little
edge cases and everyone thinks their’s is so common, which is why Java
ORM layers are so overblown and complex. The bottom line is he’s
basically bitching that belongs_to doesn’t have :dependent => :destroy,
but that’s not trivial to implement as it is for :has_many. He should
just implement it himself and be done with it.

Gabe Da silveira wrote:

I think it’s pretty dangerous to go down the road of suggesting that
someone is over-normalizing without fully understanding their
application, or even worse, to suggest that ActiveRecord is good enough
for all schemas, and if not then the schema is the problem.

I was not intending to say that AR is good for everything, or otherwise
it doesn’t make sense. What I was trying to say was that particularly,
it makes sense that there’s no :dependant => :destroy for a belongs_to
precisely because I have difficulty seeing a situation where it makes
sense. The very purpose of belongs_to is to establish a child-parent
relationship of sorts, so you can’t know if you can delete the parent.

The fact that the OP wants so dearly to destroy what should be a parent
object indicates pretty clearly to me that there’s not additional data
being stored, but rather just normalization. I recognize this particular
pattern because back in the day I considered doing something similar in
a situation where I had several different entities each with exactly one
address. The OO developer in me said I should factor out, but good
database design eventually won out and overruled.

Even if the intention was to actually store additional information, such
as a school having more than one address, then I would say that the
schema was still wrong. If entities can share an address, then there
needs to be a many to many join table. If they can’t share them, and
there’s more than one address per school, then the address table should
have the foreign key and be doing the belongs_to. If there are many
different entities that might have a parent relationship to addresses,
then the address should probably use a polymorphic relationship.

In any case, I think the schema is in error. If there is more
information concealed somewhere, then I could clearly be wrong.

On top of that, by using a separate table for the address, you’re adding
complexity to any and all database operations that involve addresses.
Where a single table approach could look up a school by address in one
super simple query, a two table approach would require an :include
directive and a lot of LEFT JOIN black magic behind the scenes. To
reiterate, this doesn’t even gain you any particular benefits.

What if you want to look up all entities with a certain address? What
if the zipcode changes for the address? Sure this schema is more
complex, but it also contains more information. The extra joins are
just the cost of the extra information. Whether or not the cost is
justified depends on whether that information is necessary. If it is,
then de-normalizing has higher costs both in terms of query complexity
as well as data maintenance the risk of corruption.

I’d rather do n separate queries (where there are n entities to look up
by address) and then just append the arrays. If you’re going to do the
:include for potentially n different relationships, then you are
significantly increasing the complexity of the queries. Even if you
exclude the complexity of the queries as an issue, the complexity of
your object model (and the statements you use to query it) increases.

On one hand, fudging your schema a little bit to work better with
ActiveRecord is a calculated sacrifice that may well be worth it. On
the other hand, adopting a worldview that your schema must conform to
the capabilities of AR will result in a dangerous dumbing down of your
data modeling skills.

I’m not suggesting that the OP fudge their schema at all. I’m suggesting
that it was intrinsically flawed to start with, and that the lack of an
AR way to go about it might be an indication of the problem.

On Tue, Aug 26, 2008 at 7:19 PM, Jurket Largit
[email protected] wrote:

put this in the parent table. You wouldn’t need any sort of “belongs_to”

class City
#nothing needed
end

“has_reference :city” == “belongs_to :city”

belongs_to :city means you have a foreign key referencing a city, like
users.city_id → cities.id.

Then, when you create a new adventure, default its starting city to
the user’s current city.

Best,
jeremy

I’m not suggesting that the OP fudge their schema at all. I’m suggesting
that it was intrinsically flawed to start with, and that the lack of an
AR way to go about it might be an indication of the problem.

The original poster is right on. Perhaps the example doesn’t make it
clear, so let me present another example.

I have a table called “cities”, which is pretty much a static lookup
table. You’ll find attributes such as: lat, long, population, name, …

I have a table called “users” for each user. When a user registers, he
specifies his “city”. Essentially a User has-one City.

So now if i add a FK in cities to point back to users, with the
corresponding belongs_to in the city model, rails is happy.

But in my app users go on adventures. When they do, their current city
gets copied over into the adventure, so that the adventure remains
static over time (w/respect to city). Eg, a user sets his city to
Chicago on wednesday, on thursday he participates in adventure A1, so
therefore A1’s city is “Chicago”. On Friday the user changes his
location to Rochester, and then participates in adventure A2. A2’s city
is now “Rochester”.

So i also have the relationship: Adventure has-one City. But how do i do
this? Do i add a column to Cities called “adventure_id” and the
corresponding belongs_to? That’s just ugly. I don’t want to keep adding
parent id columns to the city table just because some other entity wants
a relationship with a city.

Do i denormalize and include all of the city attributes in each of User
and Adventure? No way, that’s also nasty; consider a user participating
in many adventures over time.

What i really want is to add a column “city_id” to both the User table
and the Adventure table; and whatever other table might be intersted in
having a relationship with City.

In the abstract, this is the notion of a lookup table, where many
entities might have an attribute that is the FK to some specific lookup
table. The FK is in the parent table pointing to the lookup table. This
is a perfectly reasonable relational design.

It’s as if AR is missing some sort of “has_reference”; you would only
put this in the parent table. You wouldn’t need any sort of “belongs_to”
declaration in the City table, since you wouldn’t traverse the model
objects in that direction.

class User
has_reference :city
end

class Adventure
has_reference :city
end

class City
#nothing needed
end

Did I miss it or has nobody considered using a polymorphic association
for this case?

class School < ActiveRecord::Base
has_one :address, :as => :addressable
end

class Student < ActiveRecord::Base
has_one :address, :as => :addressable
end

Jeremy K. wrote:

On Tue, Aug 26, 2008 at 7:19 PM, Jurket Largit
[email protected] wrote:

put this in the parent table. You wouldn’t need any sort of “belongs_to”

class City
#nothing needed
end

“has_reference :city” == “belongs_to :city”

belongs_to :city means you have a foreign key referencing a city, like
users.city_id → cities.id.

Then, when you create a new adventure, default its starting city to
the user’s current city.

Best,
jeremy