奇怪的mongoid错误“Mongoid :: Errors :: InvalidCollection:...它是一个嵌入式文档,请从根文档中访问一个集合。”

时间:2011-11-15 11:18:03

标签: mongoid

我在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.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 :(得分:0)

因为你有

   embeds_many :groups
在Match类中定义的

关系,您不能像

那样实例化组
   Match.first.groups.new

因为匹配包含许多组(组数组),而是使用&lt;&lt;实例化新的组对象并放入组中。 (Ruby追加)运算符

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

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