I'm trying to build a text adventure game in Rails 3 (yes I know that's silly). Right now I have a model called Room. Each room needs to be associated with up to four other rooms. This relationship would be bi-directional, such that any two associated rooms would be exits for each other. So for example if I were to say:
@room1.north = @room2
@room2.south would automagically become @room1. Similarly, if I were to say:
@room1.east = nil
@room2.west also becomes nil. I would like to make this happen using only model associations, rather than doing it manually in the controller. Is this possible?
EDIT
The first example matzi gives doesn't quite work the way I want. Consider the following:
class Room < ActiveRecord::Base
attr_accessible :north, :south, :east, :west
has_one :north, :class_name => "Room", :foreign_key => "south_id"
has_one :east, :class_name => "Room", :foreign_key => "west_id"
belongs_to :south, :class_name => "Room", :foreign_key => "south_id"
belongs_to :west, :class_name => "Room", :foreign_key => "west_id"
end
@room1 = Room.new
@room2 = Room.new
@room1.save
@room2.save
This works fine:
@room1.north = @room2
@room1.north #Outputs @room2
@room2.south #Outputs @room1
@room1.north = nil
@room1.north #Outputs nil
@room2.south #Outputs nil
So far so good. But:
@room1.north = @room2
@room2.south = nil
@room1.north #Outputs @room2, but it should be nil
@room2.south #Outputs nil
Furthermore:
@room2.south = @room1
@room1.north #Outputs nil, but it should be @room2
@room2.south #Outputs @room1
See the problem here? This isn't truly bi-directional.
SOLVED
It turns out Matzi's first solution was correct after all. As he pointed out, the issue I was having with that solution was one of saving. The following works:
@room1 = Room.create
@room2 = Room.create
@room1.north = @room2
@room1.save
Room.find(1).north #Room 2
Room.find(2).south #Room 1
@room2.south = nil
@room2.save
Room.find(1).north #nil
Room.find(2).south #nil