obo
obo

Reputation: 1662

Rails3 / Mongoid : many-to-many relation and delete operation

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')]}})

Upvotes: 1

Views: 1428

Answers (1)

icanhazbroccoli
icanhazbroccoli

Reputation: 1035

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

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 'stackoverflow#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.

Upvotes: 1

Related Questions