views:

118

answers:

3
  @father = Hierarchy.find(:first, :conditions => ['label = ?', 'father'])

  @father.children.each do |child|
    puts @father.object_id == child.parent.object_id
  end

I would have thought the results here would be all true.

Instead they are all false.

Why does ActiveRecord work this way instead of recognizing that these are the same Ruby objects?

+1  A: 

Object ID is the pointer (sort of) to the object. The loading of rails objects doesn't "share" memory space, so you're getting a copy of the parent object when you do child.parent. To understand this -- you can do parent.something = foo, and subsequently compare child.parent.something and you'll see they are different. You'd have to re-load the child from the database before it will reflect the changes to the parent object.

However, odds are you're using the wrong ID value. If you want the ActiveRecord ID (e.g. the value of the ID column in your SQL DBMS), use @father.id == child.parent.id

Matt Rogish
I'm deliberately looking at the Ruby 'object_id' here rather than the AR 'id' property. My question really has to do with why AR works this way.
ula
+2  A: 

To return existing objects when possible instead of creating new ones ActiveRecord would have to keep track of which objects were created and which entry in the database they respond to, which would be some overhead. Even then it would still have to lookup child.parent in the database to know that it's the same entry that @father represents, so there wouldn't be any considerable gain performance wise from this caching (well on the ruby side it safes allocating multiple objects but at the cost of the bookkeeping overhead, but on the database side it should be basically the same).

So given that the AR people probably decided that preventing different objects corresponding to the same database entry would either be detrimental or at least not worth the effort, so they chose not to do it.

sepp2k
I think you get what I'm looking for but I don't entirely follow your explanation. You seem to be saying that in order to recognize that they're the same Ruby object, AR would have to keep a hashtable and do lookups. Perhaps. But I don't think that would necessarily involve extra overhead since AR has to cache its results anyway in case you ask for them a second time.
ula
+1  A: 

Reusing objects is problematic. What if you make changes to a model instance, but before you save it, you do another find that brings back that same object? The new one should reflect the database, but the old one should still have the changed data.

So yes, it would be a lot of overhead to keep track of each instance and the dirty fields in each one. The memory savings would not be worth the effort.

Sarah Mei
Don't some ORMs use an Identity Map for this purpose?
ula