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

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

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).

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

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?