Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphic associations in Rails 3

I think I'm going crazy.

Let's say I have 3 models: Address, Warehouse, Category:

class Address < ActiveRecord::Base
  belongs_to :category
  belongs_to :addressable, :polymorphic => true

  scope :billing_addresses , where(:categories => {:name => 'billing'}).joins(:category)  
  scope :shipping_addresses , where(:categories => {:name => 'shipping'}).joins(:category) 

end 


class Category < ActiveRecord::Base
  has_many :addresses
  has_many :subcategories, :class_name  => "Category", :foreign_key => "category_id"
  belongs_to :category, :class_name => "Category"  
end


class Warehouse < ActiveRecord::Base
  has_many :addresses, :as => :addressable
end

Address is polymorphic, because eventually I'll be using it to store addresses for clients, people, employees etc. Also each address can be of a certain type: billing, shipping, work, home, etc.

I'm trying to pull some information on a page.

@some_warehouse = Warehouse.first

Then in my view:

%b= @some_warehouse.name
%b= @some_warehouse.billing_address.address_line_1

Etc.

I end up doing a lookup for each line of information.

I tried to do things like

Warehouse.includes(:addresses).where(:name => "Ware1")
Warehouse.joins(:addresses).where(:name => "Ware1")

And various variations of that. No matter what I don' I can't get rails to preload all the tables. What am I doing wrong?

like image 315
konung Avatar asked Mar 01 '11 02:03

konung


1 Answers

Here are revised models, that do appropriate joins in sql and reduce number of quesries from 16 to 8, one for each piece of info, instead of multiples ones that also do lookup categories, etc.:

class Address < ActiveRecord::Base
  belongs_to :category
  belongs_to :addressable, :polymorphic => true

  scope :billing_addresses ,  where(:categories => {:name => 'billing'}).includes(:category)
  scope :shipping_addresses , where(:categories => {:name => 'shipping'}).includes(:category)

end

class Warehouse < ActiveRecord::Base
  has_many :addresses,  :as => :addressable,  :include => :category, :dependent => :destroy

  def billing_address
    self.addresses.billing_addresses.first
  end    
  def shipping_address
    self.addresses.shipping_addresses.first
  end   
end


class Category < ActiveRecord::Base
  has_many :addresses
  has_many :subcategories, :class_name  => "Category", :foreign_key => "category_id"
  belongs_to :category, :class_name => "Category"  
end

Sleep helps. Also not forgetting to reload console from time to time :-)

like image 185
konung Avatar answered Sep 19 '22 02:09

konung