After_initialize and after_find

Hello,

I need to do some initialization on instances that involve an
associated model.
This means that when I find an object, it immediately does another
query to get its association.
To cancel the double query, I make sure the associated model gets pre-
loaded by using :include when retrieving the object.
Only, it seems that after_initialize or after_find get triggered
before activerecord does its associating-trick.
No matter what I try, finding the object always triggers another
query.

I guess this has to do with the order callbacks get called.
Is there any way to circumvent this?

Thanks,
Mathijs

Like I said, I tried that, it doesn’t work in this case.
My guess is that in after_find the associations aren’t loaded yet
(they are included in the query, but they aren’t parsed yet).

Model.find(:first, :include => “association”)

On Jan 25, 2008 9:01 AM, [email protected]
[email protected]
wrote:

before activerecord does its associating-trick.


Ryan B.
http://www.frozenplague.net
Feel free to add me to MSN and/or GTalk as this email.

A quick pass through the ARec code suggests that after_find does not
introduce the kinds of double-queries that you’re talking about. Any
time the :include option is passed into #find the call is delegated to
ARec::Associations#find_with_associations. That method retrieves
records using a join and then calls instantiate on each record.
Instantiate, in turn, calls after_find and after_initialize as the
last two steps before returning the object to the caller. This was
only a cursory look on my part but it does not appear that there are
any chances for associations to be loaded later.

If you post the code in question we can probably be of more
assistance.

Regards,
AndyV

On Jan 25, 7:01 am, “[email protected]

Sorry for my late reply,

here is some example code(stupid example but it does the trick):
create_table “people”, :force => true do |t|
t.string “name”
t.datetime “created_at”
t.datetime “updated_at”
end

create_table “pets”, :force => true do |t|
t.string “name”
t.string “kind”
t.string “person_id”
t.datetime “created_at”
t.datetime “updated_at”
end

class Person < ActiveRecord::Base
has_many :pets
end

class Pet < ActiveRecord::Base
belongs_to :person
attr_accessor :fullname

def after_find
self.fullname = “#{person.name}'s #{kind}”
end
end

on console:
m=Person.new
m.name = “Mathijs”
m.save
f=m.pets.build
f.name=“fishy”
f.kind=“goldfish”
f.save

now when I do this:
Pet.find(:first, :include => :person)

I get this in my log:
Pet Load Including Associations (0.000385) SELECT pets.“id” AS
t0_r0, pets.“name” AS t0_r1, pets.“kind” AS t0_r2, pets.“person_id” AS
t0_r3, pets.“created_at” AS t0_r4, pets.“updated_at” AS t0_r5,
people.“id” AS t1_r0, people.“name” AS t1_r1, people.“created_at” AS
t1_r2, people.“updated_at” AS t1_r3 FROM pets LEFT OUTER JOIN people
ON people.id = pets.person_id
Person Load (0.000249) SELECT * FROM people WHERE (people.“id” =
1)

So it appears after_find still insists of loading the person, which
was already loaded by :include => :person

Is this normal behavior?