Err the Blog Atom Feed Icon
Err the Blog
Rubyisms and Railities
  • “has_many :as”
    – PJ on August 17, 2006

    On an actual website we’re building (gasp) in Rails, we have a bunch of content types that have promotions.

    Here’s the schema for our promotions table:

    create_table :promotions do |t|
      t.column :size,       :integer
      t.column :content,    :text
      t.column :item_type,  :string
      t.column :item_id,    :integer
      t.column :created_at, :datetime
    end
    

    And the the association code to wire up the promotions:

    class Story < ActiveRecord::Base
      has_many :promotions, :conditions => ["item_type = ?", self.class.to_s],
                            :foreign_key => "item_id"
    end
    
    class Product < ActiveRecord::Base
      has_many :promotions, :conditions => ["item_type = ?", self.class.to_s],
                            :foreign_key => "item_id"
    end
    

    Which gives us the ability to do story.promotions or product.promotions and the model code is exactly the same. It’s straightforward without any unnecessary fuss, but Rails does provide some magic to make it even cleaner:

    class Story < ActiveRecord::Base
      has_many :promotions, :as => :item
    end
    
    class Product < ActiveRecord::Base
      has_many :promotions, :as => :item
    end
    

    Yes, I’ll admit, for all of the shit I give Rails it does do some pretty cool stuff.

  • Soren Burkhart, 2 days later:

    That is nice! I was just about to setup a similar model to track transactions by user type like your first design, but the has_many, :as is perfect.

  • One person has commented.
    Chime in.
    Sorry, no more comments :(
This is Err, the weblog of PJ Hyett and Chris Wanstrath.
All original content copyright ©2006-2008 the aforementioned.