Rails3 / Mongoid:多对多关系和删除操作

时间:2022-10-04 10:39:58

I have the following model :

我有以下型号:

class User
  include Mongoid::Document
  include Mongoid::Timestamps

  has_and_belongs_to_many :challenged, class_name: "Event", inverse_of: "challengers"

  def challenge!(event)
    self.challenged << event
    self.save!
  end

  def unchallenge!(event)
    self.challenged.where(_id: event.id).destroy_all
    self.save!
  end
end

class Event
  include Mongoid::Document
  include Mongoid::Timestamps

  has_and_belongs_to_many :challengers, class_name: "User", inverse_of: "challenged"
end

The challenge! method works fine, but the unchallenge! one does not. If I test it with the following code :

挑战!方法工作正常,但没有挑战!一个没有。如果我用以下代码测试它:

require 'spec_helper'

describe User do
  before(:each) do
    @user = User.create!
    @event = Event.create!
  end

  it "should unchallenge an event" do
    @user.challenge!(@event)
    @user.unchallenge!(@event)
    @user.challenged.should_not include(@event)
  end

end

The test fails ; so it seems that the delete operation did not work.

测试失败;所以似乎删除操作不起作用。

The application logs are :

应用程序日志是:

MONGODB test_mongo_test['users'].insert([{"challenged_ids"=>[], "_id"=>BSON::ObjectId('4f2d13fdbd028603f7000001')}])
MONGODB test_mongo_test['system.namespaces'].find({})
MONGODB test_mongo_test['events'].insert([{"challenger_ids"=>[], "_id"=>BSON::ObjectId('4f2d13fdbd028603f7000002')}])
MONGODB test_mongo_test['events'].update({"_id"=>BSON::ObjectId('4f2d13fdbd028603f7000002')}, {"$addToSet"=>{"challenger_ids"=>{"$each"=>[BSON::ObjectId('4f2d13fdbd028603f7000001')]}}})
MONGODB test_mongo_test['users'].update({"_id"=>BSON::ObjectId('4f2d13fdbd028603f7000001')}, {"$pushAll"=>{"challenged_ids"=>[BSON::ObjectId('4f2d13fdbd028603f7000002')]}})
MONGODB test_mongo_test['$cmd'].find({"count"=>"events", "query"=>{"$and"=>[{:_id=>{"$in"=>[BSON::ObjectId('4f2d13fdbd028603f7000002')]}}, {:_id=>BSON::ObjectId('4f2d13fdbd028603f7000002')}]}, "fields"=>nil}).limit(-1)
MONGODB test_mongo_test['events'].remove({"$and"=>[{:_id=>{"$in"=>[BSON::ObjectId('4f2d13fdbd028603f7000002')]}}, {:_id=>BSON::ObjectId('4f2d13fdbd028603f7000002')}]})
MONGODB test_mongo_test['events'].find({:_id=>{"$in"=>[BSON::ObjectId('4f2d13fdbd028603f7000002')]}})
MONGODB test_mongo_test['events'].find({:_id=>{"$in"=>[BSON::ObjectId('4f2d13fdbd028603f7000002')]}})

1 个解决方案

#1


1  

Check your application log

检查应用程序日志

If I'm right self.challenged returns Event criteria, not User criteria, so fix is:

如果我是正确的自己。挑战返回事件标准,而不是用户标准,所以修复是:

self.challenged.where(_id: event.id).destroy_all

self.challenged.where(_id:event.id).destroy_all

Upd:

UPD:

I've written same test as you did( just different model names ):

我和你一样编写了相同的测试(只是不同的模型名称):

# announcement_list.rb
def challenge!(announce)
  self.announcements << announce
  self.save!
end

def unchallenge!(announce)
  self.announcements.where( _id: announce.id ).destroy_all
  self.save!
end

#anouncement_list_spec.rb
context '*#9132596' do
  let!( :announcement_list ) { Factory( :announcement_list ) }
  let!( :announcement ) { Factory( :announcement ) }
  it 'kick announcement out of list on unchallenge! method call' do
    announcement_list.challenge!( announcement )
    announcement_list.unchallenge!( announcement )
    announcement_list.announcements.should_not include( announcement )
  end
end

This way i get my tests failed. Then I change:

这样我的测试失败了。然后我改变:

def unchallenge!(announce)
  self.announcements.destroy_all( conditions: { _id: announce.id })
  self.save!
end

Yap, little bit tricky, and definitely should be placed in mongoid tracker. Hope this will help you.

哎呀,有点棘手,绝对应该放在mongoid跟踪器中。希望这会帮助你。

#1


1  

Check your application log

检查应用程序日志

If I'm right self.challenged returns Event criteria, not User criteria, so fix is:

如果我是正确的自己。挑战返回事件标准,而不是用户标准,所以修复是:

self.challenged.where(_id: event.id).destroy_all

self.challenged.where(_id:event.id).destroy_all

Upd:

UPD:

I've written same test as you did( just different model names ):

我和你一样编写了相同的测试(只是不同的模型名称):

# announcement_list.rb
def challenge!(announce)
  self.announcements << announce
  self.save!
end

def unchallenge!(announce)
  self.announcements.where( _id: announce.id ).destroy_all
  self.save!
end

#anouncement_list_spec.rb
context '*#9132596' do
  let!( :announcement_list ) { Factory( :announcement_list ) }
  let!( :announcement ) { Factory( :announcement ) }
  it 'kick announcement out of list on unchallenge! method call' do
    announcement_list.challenge!( announcement )
    announcement_list.unchallenge!( announcement )
    announcement_list.announcements.should_not include( announcement )
  end
end

This way i get my tests failed. Then I change:

这样我的测试失败了。然后我改变:

def unchallenge!(announce)
  self.announcements.destroy_all( conditions: { _id: announce.id })
  self.save!
end

Yap, little bit tricky, and definitely should be placed in mongoid tracker. Hope this will help you.

哎呀,有点棘手,绝对应该放在mongoid跟踪器中。希望这会帮助你。