views:

57

answers:

1

ActiveRecord gives you an interesting error when you try to eager-load a non-existent association. It looks something like this:

ActiveRecord::ConfigurationError: Association named 'secondary_complaint' was not found; perhaps you misspelled it?

Now why the hell would anybody want to preload a non-existent association? Check this out.

class Bitchy < ActiveRecord::Base
  has_one :primary_complaint, :as => :whiny_bitch, :class_name => 'Complaint', :conditions => {:complaint_type => 'primary'}
  has_one :secondary_complaint, :as => :whiny_bitch, :class_name => 'Complaint', :conditions => {:complaint_type => 'secondary'}

  has_one :life, :as => :humanoid
end


class Whiny < ActiveRecord::Base
  has_one :primary_complaint, :as => :whiny_bitch, :class_name => 'Complaint', :conditions => {:complaint_type => 'primary'}

  has_one :life, :as => :humanoid
end

class Complaint < ActiveRecord::Base
  belongs_to :whiny_bitch, :polymorphic => true
end

class Life < ActiveRecord::Base
  belongs_to :humanoid, :polymorphic => true
end

# And here's the eager-loading part:
Life.all(:include => {:humanoid => [:primary_complaint, :secondary_complaint]})

The above code has interesting peculiarity. If you only have Bitchy as your humanoids - it will actually work. However, as soon as a single Whiny appears — you're in trouble. ActiveRecord starts whining the error I wrote above - Association named 'secondary_complaint' was not found. You see why, right? Because not every humanoid has a secondary_complaint.

Is there a way to make ActiveRecord stop bitching and whining when I'm trying to eager load polymorphic associations which may or may not have certain has_one associations attached to them?

A: 

I know this is probably just for the sake of your example, but you could change it to has_many :complaints so they both have the same association, and then pull out the primary or secondary types from that.

Andrew Vit
I'm definitely thinking about switching to has_many here for the sake of this optimization to work. The worst part is that having the `[:primary_comlaint, :secondary_complaint]` in eager loading is a decisive factor between having and not having N+1 issue. I don't even consider it optimization frankly, I consider it a given that there shall never be N+1 in public-driven code.But before resorting to that, I'd love to try find alternative routes.
hakunin
I guess generally this would be a better way to accomplish this, in the mean time I disabled eager loading for this scenario. Will optimize later. Accepting. :)
hakunin