Friday, May 6, 2011

Eager loading not working in Rails 2.2.2

I'm working with models analogous to the following:

class Owner < ActiveRecord::Base
  has_many :owned
end

class Owned < ActiveRecord::Base
  belongs_to :owner
end

You can presume that owned_id and owner_id are in the right places. The trouble is that, in a controller for a different mvc chain in the app,

@owner = Owned.find_by_id(owned_id, :include => :owner)

doesn't work. I get the owner_id, column, naturally, but can't then do

@owned.owner # is just nil

What gives? I mean, I could do the assignment directly before passing the result on to the view:

@owned.owner = Owner.find_by_id(@owned.owner_id)

but that just seems silly. Come on, embarrass me. What's the obvious thing that I've missed? This works in other places in my app, but I can't spot the differences. Are there some common traps? Anything helps.

Thank you

From stackoverflow
  • I just keep winning. The corresponding 'Owner' object had been deleted from the owners table.

    The funny thing is, before I created an account, I had tons of karma on my cookie-based identity. Then my cookies became corrupted, and I can't ask anything but stupid questions anymore, and my karma sits at 1. Oh well.

    klew : Don't worry ;). Most of my answers has 0 points. Ask a good question isn't easy. Try answering some questions and don't give up!
  • Hi Mike,

    Reputation on StackOverflow is not cookie based. You may have to log in again or something.

    Your question seems to imply that you have an owned_id field in the owner table. You don't need that and should remove it.

    You just need an owner_id integer field in the owned table.

    You can access your records and relationships in a number of ways. First let's start by accessing the owner record first.

    owner = Owner.find(owner_id)
    owned = owner.owned # this is an array since you a 'has_many' relationship
    

    Normally you'd want to access the owned records in the following way:

    for owned in owner.owned
     puts owned.name # or access any other attributes
    end
    

    If you would like to access the owned records first you could do the following:

    @owned = Owned.find(:all, :conditions => [ "owner_id = ?", owner_id ])
    # @owned is an array so you need to iterate through it
    for owned in @owned
      puts owned.owner.name # or access any other attribute from the owner
    end
    

    Once you've got these queries working fine you can worry about eager loading by adding :include in your find statements. Note that this can be of interest for optimization but not necessary from the get go.

    I hope this helps.

0 comments:

Post a Comment