Странная ошибка mongoid "Mongoid :: Errors :: InvalidCollection: ... это встроенный документ, пожалуйста, обратитесь к коллекции из корневого документа." - PullRequest
1 голос
/ 15 ноября 2011

Я получаю эту ошибку в моем приложении rails 3.

Mongoid::Errors::InvalidCollection: Access to the collection for Match is not allowed since it is an embedded document, please access a collection from the root document.

Вот соответствующая структура кода

Класс матча

Stateflow.persistence = :mongoid
class Match < GmMongo::Base
  include Stateflow
  #attributes
  field :name, :type=>String
  field :match_type, :type=>String
  field :state

  #state transistions
  stateflow do
    state_column :state
    initial :unlocked
    state :unlocked
    state :locked
    event :lock do
      transitions :from => :unlocked, :to => :locked
    end
    event :unlock do
      transitions :from => :locked, :to => :unlocked
    end
  end

  #relations
  embeds_many :players
  has_many :messages, :class_name=>:match_messages.to_s.classify
  belongs_to :game
  embeds_many :groups

  #validations
  validates_presence_of :name
  validates_presence_of :match_type

  def send_message(match_message)
    # #TODO: raise exception if the argument is invalid. i.e. Not of class MatchMessage
    options = {}
    unless match_message.target_user.blank?
      options = {
        :audience=>:single_player,
        :target_player=>match_message.target_user
        }
    else
      unless match_message.group.blank?
      options = {
        :audience=>:group,
        :group=>match_message.group
        }
      else
        options = {
          :audience=>:match,
          :match=>match_message.match
        }
      end
    end
    args = OpenHash[{
      :message=>match_message.content,
      :game_id=>match_message.match.game.id,
    }.merge(options)]
    Message.send_notification(args)
    #Set the sent_at attribute for message being sent.
    match_message.sent_at=Time.now
    match_message.save!
  end

  def get_devices
    self.players.collect{|player| player.device}
  end
end

Класс игрока

class Player
  include Mongoid::Document
  #belongs_to :user
  #belongs_to :device
  field :user_id, :type=>BSON::ObjectId
  field :device_id, :type=>BSON::ObjectId
  has_many :sent_messages, :class_name=>"MatchMessage", :foreign_key=>:sender_id
  has_many :targeted_messages, :class_name=>"MatchMessage", :foreign_key=>:target_user_id
  embedded_in :match
  embedded_in :group
  validates_presence_of :user
  validates_presence_of :device
  validates_presence_of :match
  validates_uniqueness_of :user_id, :scope => [:device_id, :match_id], :message=>"Player already exists."

  #A workaround for mixing relational and embedded references
  def user=(user)
    self[:user_id]=user.id
  end

  def user
    User.find(self.user_id) unless self.user_id.blank?
  end

  def device=(device)
    self[:device_id]=device.id
  end

  def device
    Device.find(self.device_id)  unless self.device_id.blank?
  end
end

Класс группы

class Group < GmMongo::Base
  field :name, :type=>String
  embedded_in :match
  #embeds_many :players
  #has_many :messages, :class_name=>:match_messages.to_s.classify
  validates_presence_of :name, :message=>"Please provide a name for this group."
  validates_uniqueness_of :name, :scope => [:match_id], :message=>"This group in this match already exists."

  def get_devices
    self.players.collect{|player| player.device}
  end
end

Группа и игрок встроены в Match.

Когда я пытаюсь запустить

Match.first.groups.new

Я получаю эту ошибку

Mongoid::Errors::InvalidCollection: Access to the collection for Match is not allowed since it is an embedded document, please access a collection from the root document.

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 15 ноября 2011

Поскольку у вас есть отношение

   embeds_many :groups

, определенное в классе Match, вы не можете создать экземпляр группы, например

   Match.first.groups.new

, потому что Match содержит много групп (массив групп), вместо этого создайте экземплярновый объект группы и поместите в группы с помощью оператора << (Ruby append) </p>

   Match.first.groups << Group.new(:params)

или

   group = Group.new(:params)
   Match.first.groups << group
...