views:

91

answers:

1

Using Mongoid, let's say I have the following classes:

class Map
  include Mongoid::Document

  embeds_many :locations
end

class Location
  include Mongoid::Document

  field :x_coord, :type => Integer
  field :y_coord, :type => Integer

  embedded_in      :map, :inverse_of => :locations
end


class Player
  include Mongoid::Document

  references_one   :location
end

As you can see, I'm trying to model a simple game world environment where a map embeds locations, and a player references a single location as their current spot.

Using this approach, I'm getting the following error when I try to reference the "location" attribute of the Player class:

Mongoid::Errors::DocumentNotFound: Document not found for class Location with id(s) xxxxxxxxxxxxxxxxxxx.

My understanding is that this is because the Location document is embedded making it difficult to reference outside the scope of its embedding document (the Map). This makes sense, but how do I model a direct reference to an embedded document?

A: 

My current workaround is to do the following:

class Map
  include Mongoid::Document

  embeds_many     :locations
  references_many :players, :inverse_of => :map
end

class Player
  referenced_in :map
  field :x_coord
  field :y_coord

  def location=(loc)
    loc.map.users << self
    self.x_coord = loc.x_coord
    self.y_coord = loc.y_coord
    self.save!
  end

  def location
    self.map.locations.where(:x_coord => self.x_coord).and(:y_coord => self.y_coord).first
  end  
end

This works, but feels like a kluge.

Scott Brown