开发者

How do I delete an embedded doc from Mongoid?

I'm having some issues deleting my document using Mongoid... The code actually does delete the gallery, but I get a browser error which looks like:

Mongoid::Errors::DocumentNotFound at /admin/galleries/delete/4e897ce07df6d15a5e000001

The suspect code is below:

def self.removeGalleryFor(user_session_id, gallery_id)
  person = Person.any_in(session_ids: [user_session_id])
  return false if person.count != 1
  return false if person[0].开发者_Go百科userContent.nil?
  return false if person[0].userContent.galleries.empty?

  gallery = person[0].userContent.galleries.find(gallery_id) #ERROR is on this line
  gallery.delete if !gallery.nil?
end

My Person class embeds one userContent which embeds many galleries.

Strangely enough I've got a couple of tests around this which work fine...

I'm really not sure what's happening - my gallery seems to be found fine, and is even deleted from Mongo.

Any ideas?


find throws an error if it can't find a document with the given id. Instead of checking presence of given gallery and returning nil if it doesn't exist, you directly ask mongodb while querying to remove any such gallery.

def self.remove_gallery_for(user_session_id, gallery_id)
  user_session_id = BSON::ObjectId.from_string(user_session_id) if user_session_id.is_a?(String)
  gallery_id = BSON::ObjectId.from_string(gallery_id) if gallery_id.is_a?(String)

  # dropping to mongo collection object wrapped by mongoid, 
  # as I don't know how to do it using mongoid's convenience methods
  last_error = Person.collection.update(
      # only remove gallery for user matching user_session_id
      {"session_ids" => user_session_id}, 
      # remove gallery if there exists any
      {"$pull" => {:userContent.galleries => {:gallery_id => gallery_id}}},
      # [optional] check if successfully removed the gallery
      :safe => true
  )

  return last_error["err"].nil?
end

This way you do not load the Person, you don't even get the data from monogdb to application server. Just get the gallery removed if it exists.

But you should prefer @fl00r's answer if you need to fire callbacks and switch to destroy instead of delete


def self.removeGalleryFor(user_session_id, gallery_id)
  # person = Person.where(session_ids: user_session_id).first
  person = Person.any_in(session_ids: [user_session_id])
  if person && person.userContent && person.userContent.galleries.any?
    gallery = person.userContent.galleries.where(id: gallery_id).first
    gallery.delete if gallery
  end
end

ps:

In Ruby usually under_score naming rather then CamelCase is used


Kudos to Rubish for pointing me to a solution that at least passes my tests - for some reason fl00r's code didn't work - it looks like it should, but doesn't for some reason...

Person.collection.update(
    {"session_ids" => user_session_id},
    {"$pull" => {'userContent.galleries' => {:_id => gallery_id}}},
    :safe => true
)

=> this code will pass my tests, but then once it's running in sinatra it doesn't work.... so frustrating!

have posted this code with tests on github https://github.com/LouisSayers/bugFixes/tree/master/mongoDelete

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜