Thursday, December 16, 2010

Self-Referential Rails Association

Or, doing terrible things to my relational db with a fork, part one.

I often want trees of objects. To do this with ActiveRecord, establish a self-referential association. Let's get started with a simple model and a join table:

rails generate scaffold Item name:string description:text
rails generate model ItemItem parent_id:integer child_id:integer rank:integer
rake db:migrate

Now lets wire things up:

class ItemItem < ActiveRecord::Base
belongs_to :parent, :class_name => "Item"
belongs_to :child, :class_name => "Item"
end
class Item < ActiveRecord::Base
has_many :below, :class_name => "ItemItem", :foreign_key => "parent_id"
has_many :children, :through => :below
has_one :above, :class_name => "ItemItem", :foreign_key => "child_id"
has_one :parent, :through => :above
end

Set aside a few minutes to work through this with the Rails guide. You'll find it's all standard association stuff, just without the default naming by convention. In the meantime, enjoy:

irb(main):001:0> i = Item.new :name => 'Buy Presents'
=> #<item>
irb(main):002:0> j = Item.new :name => 'Big Newegg Order'
=> #<item>
irb(main):003:0> i.children << j
=> [#<item>]

Note that hideous db interactions (i.save and j.reload) must be engaged in before j.parent works :(.

No comments:

Post a Comment