Skip to content

Instantly share code, notes, and snippets.

@apneadiving
Created April 14, 2012 20:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save apneadiving/2387723 to your computer and use it in GitHub Desktop.
Save apneadiving/2387723 to your computer and use it in GitHub Desktop.
potential mongoid bug
--------------------------------------------------------------------------------------------
With one object saved, another in memory
--------------------------------------------------------------------------------------------
#setup
subject.copywriter_languages.create Factory.attributes_for(:copywriter_language, status: "deleted")
subject.copywriter_languages.build Factory.attributes_for(:copywriter_language, status: "pending")
#Round 1
#checking default scope
subject.copywriter_languages.criteria
=> #<Mongoid::Criteria
selector: {:status=>{"$ne"=>"deleted"}},
options: {},
class: CopywriterLanguage,
embedded: true>
subject.copywriter_languages.count
=> 1
subject.copywriter_languages.first.status
=> "deleted"
# another weirdness: count wasn't supposed to be eq 1?
subject.copywriter_languages.map &:status
=> ["deleted", "pending"]
#this seems logic but why do I have an unsaved object here?
subject.copywriter_languages.unscoped.count
=> 2
#Round 2
#This finally works but retrieves the unsaved object
subject.copywriter_languages.where(:status.ne => :deleted)
=> #<Mongoid::Criteria
selector: {:status=>{"$ne"=>"deleted"}},
options: {},
class: CopywriterLanguage,
embedded: true>
#seems it finds the unsaved object
subject.copywriter_languages.where(:status.ne => :deleted).count
=> 1
subject.copywriter_languages.where(:status.ne => :deleted).first.status
=> "pending"
--------------------------------------------------------------------------------------------
When two objects in db
--------------------------------------------------------------------------------------------
#setup
subject.copywriter_languages.create Factory.attributes_for(:copywriter_language, status: "deleted")
subject.copywriter_languages.create Factory.attributes_for(:copywriter_language, status: "pending")
#Round 1
#checking default scope
subject.copywriter_languages.criteria
=> #<Mongoid::Criteria
selector: {:status=>{"$ne"=>"deleted"}},
options: {},
class: CopywriterLanguage,
embedded: true>
#wring behavior
subject.copywriter_languages.count
=> 2
#proof
subject.copywriter_languages.map &:status
=> ["deleted", "pending"]
#Round 2
# works as expected. So same criteria as above but different result
subject.copywriter_languages.where(:status.ne => :deleted).criteria
=> #<Mongoid::Criteria
selector: {:status=>{"$ne"=>"deleted"}},
options: {},
class: CopywriterLanguage,
embedded: true>
subject.copywriter_languages.where(:status.ne => :deleted).count
=> 1
subject.copywriter_languages.where(:status.ne => :deleted).first.status
=> "pending"
class LanguageSkill
include Mongoid::Document
default_scope where(:status.ne => "deleted")
field :status, :type => String, :default => "pending"
end
class CopywriterLanguage < LanguageSkill
embedded_in :profile, :inverse_of => :copywriter_languages, :validate => false
end
@rubish
Copy link

rubish commented Apr 17, 2012

Might be some issue with the default scope, can you try subject.copywriter_languages.unscoped and see if it has an empty selector. If it does then try to see subject.copywriter_languages.unscoped.count. I guess there are two different documents existing in db, but default scope is somehow creating issues and behaving strangely. You should update mongoid if you can and take a look at http://stackoverflow.com/questions/7357947/rails-mongoid-clear-criteria/7360803#7360803 if you can't

@apneadiving
Copy link
Author

@rubish: this was an issue, and the fix will be reeased in 2.4.9: https://github.com/mongoid/mongoid/issues/1917

@rubish
Copy link

rubish commented Apr 17, 2012 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment