Ruby ActiveRecord: How to connect two rooms with an exit -
i making small text-adventure, , want use activerecord object relational mapping.
what i'm having trouble with, understanding how connect 2 rooms using exit. following facts given:
- a room can have multiple exits
- an exit can in different directions (it has 'direction' field). also, might have other parameters such 'locked', etc. want add later.
- an exit connects 2 rooms.
however, stuck:
what have far
class room < activerecord::base has_many :exits has_many :neighbours, through: :exits end class exit < activerecord::base belongs_to :room, dependent: :destroy belongs_to :room_dest, foreign_key: "room_dest_id", class_name: "room", dependent: :destroy end
but incomplete. room.neighbours
, example, not working @ all.
what baffles me how make exits work two-ways: if add exit on 1 room, won't in room.exits
list in other room.
what works is: (given exit connecting room1
, room2
) room1.first.exits.first.room_dest
(this room2
) room2.exits
empty, , room1.neighbours
shows list containing itself.
how done properly?
to room.neighbours working, believe first need change
belongs_to :room_dest, foreign_key: "room_dest_id", class_name: "room", dependent: :destroy
to
belongs_to :neighbour, foreign_key: "room_dest_id", class_name: "room"
note removed dependent: option because don't want destroy rooms when exits deleted. want dependent: :destroy on has_many relationship exits.
now we've solidified one-way binding of exit. if think it, isn't "exit" one-way definition? while seems limiting @ first, can utilize define "entrances" of room. connection neighbour original room. like:
has_many :entrances, class_name: "exit", foreign_key: "room_dest_id"
or define method queries exits , checks if either room_id or room_dest_id room id. in case rename "exit" class more generic. unfortunately can't think of built-in ar association multi-key association you. wouldn't work right because things association.build/create not know of keys set. it's relatively simple method or set of methods still return scope operator on:
has_many :connections, dependent: :destroy # ease of creating connection, not useful querying them def exits connection.where(["room_id = :id or dest_room_id = :id", id: self.id]) end def neighbours exits.map |conn| conn.room_id == self.id ? conn.dest : conn.source end end
you make query more complex if want of connections one-way. or write other methods build on since not executed immediately. still chain .first(), .where(), etc on it.
Comments
Post a Comment