-
Type: Task
-
Resolution: Done
-
Affects Version/s: None
-
Component/s: None
I ran in a problem, which is related to MONGOID-1143 + MONGOID-768 and the changes made in 2.2.0 to fix them.
I have the following test:
it "should update a users role on PUT" do user = Factory.create(:admin, :user_roles => ['user']) User.find(user.id).user_roles.should eq ['user'] put :update, :id => user.id, :user => { :user_roles => ['admin'] } response.should be_redirect User.find(user.id).user_roles.should eq ['admin'] end
and my User and Role Class look like this:
class User include Mongoid::Document embeds_many :roles def user_roles=(new_roles) self.roles = new_roles.collect { |role_name| Role.new(:name => role_name) unless role_name.blank? } end def user_roles roles.map { |r| r.name } end end class Role include Mongoid::Document field :name, :type => String embedded_in :user end
When i run the test i get
Failure/Error: User.find(user.id).user_roles.should eq ['admin'] expected ["admin"] got ["user", "admin"]
and the logs show this line:
MONGODB crowdmedia_pages_test['users'].update({"_id"=>BSON::ObjectId('4e65fbb08095296386000022')}, {"$pushAll"=>{"roles"=>[{"name"=>"admin", "_id"=>BSON::ObjectId('4e65fbb08095296386000025')}]}})
i checked the mongodb docs and lerned that a pushAll appends the array to the field, so i modified my code:
def user_roles=(new_roles) self.roles = [] self.roles = new_roles.collect { |role_name| Role.new(:name => role_name) unless role_name.blank? } end # test results in: Failure/Error: User.find(user.id).user_roles.should eq ['admin'] expected ["admin"] got ["user"] # log shows: MONGODB crowdmedia_pages_test['users'].update({"_id"=>BSON::ObjectId('4e65fd3a809529645d000022')}, {"$unset"=>{"roles"=>true}, "$pushAll"=>{"roles"=>[{"name"=>"admin", "_id"=>BSON::ObjectId('4e65fd3a809529645d000025')}]}})
looks like none of these changes got saved...
what solved the problem is:
def user_roles=(new_roles) self.roles = [] self.save self.roles = new_roles.collect { |role_name| Role.new(:name => role_name) unless role_name.blank? } end # logs: MONGODB crowdmedia_pages_test['users'].update({"_id"=>BSON::ObjectId('4e65fded80952964b8000022')}, {"$unset"=>{"roles"=>true}}) MONGODB crowdmedia_pages_test['$cmd'].find({"count"=>"users", "query"=>{:email=>/^johnnie23@email\.com$/i, :_id=>{"$ne"=>BSON::ObjectId('4e65fded80952964b8000022')}}, "fields"=>nil}) MONGODB crowdmedia_pages_test['users'].update({"_id"=>BSON::ObjectId('4e65fded80952964b8000022')}, {"$pushAll"=>{"roles"=>[{"name"=>"admin", "_id"=>BSON::ObjectId('4e65fded80952964b8000025')}]}})
now my tests are passing but it feels strange to put a self.save in a method which get triggered by an update_attributes call to save the model... and i got an additional query to the db
am i missing something or is it a bug in mongoid?
would be great to get some feedback to this issue!
cc tobsch