Mongoid not updating correct embedded collection objects

I have a portfolio document with an array of inline documents PortfolioItem portfolio_items. Each of them has a different array of image images. Somehow I can update the first object in the array like here:

Started PATCH "/admin/portfolios/5436dc1c646172844b000000/portfolio_items/5436dc27646172844b010000/images/5436dc40646172844b020000" for 127.0.0.1 at 2014-10-14 17:06:13 -0300
Processing by Admin::ImagesController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"hHz3W90KMgGK+LGtjLMGQmx295tvva6IFIcD4gqgG+8=", "image"=>{"title"=>"img 1", "description"=>"", "technique"=>"", "date"=>"", "public"=>"0"}, "commit"=>"Atualizar Image", "portfolio_id"=>"5436dc1c646172844b000000", "portfolio_item_id"=>"5436dc27646172844b010000", "id"=>"5436dc40646172844b020000"}
  MOPED: 127.0.0.1:27017 QUERY        database=portfolio_development collection=admins selector={"$query"=>{"_id"=>BSON::ObjectId('4cb5fbc04174a17926000002')}, "$orderby"=>{:_id=>1}} flags=[] limit=-1 skip=0 batch_size=nil fields=nil runtime: 1.2910ms
  MOPED: 127.0.0.1:27017 QUERY        database=portfolio_development collection=portfolios selector={"_id"=>BSON::ObjectId('5436dc1c646172844b000000')} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 2.6960ms
  MOPED: 127.0.0.1:27017 UPDATE       database=portfolio_development collection=portfolios selector={"_id"=>BSON::ObjectId('5436dc1c646172844b000000'), "portfolio_items._id"=>BSON::ObjectId('5436dc27646172844b010000'), "portfolio_items.0.images._id"=>BSON::ObjectId('5436dc40646172844b020000')} update={"$set"=>{"portfolio_items.0.images.$.public"=>false}} flags=[]
                         COMMAND      database=portfolio_development command={:getlasterror=>1, :w=>1} runtime: 1.2640ms
Redirected to http://0.0.0.0:3000/admin/portfolios/5436dc1c646172844b000000/portfolio_items/5436dc27646172844b010000/images/5436dc40646172844b020000/edit
Completed 302 Found in 21ms

      

but if I try to update another one, with an equivalent output that is correct for the object I want to update

Started PATCH "/admin/portfolios/5436dc1c646172844b000000/portfolio_items/5436dc27646172844b010000/images/5436de41646172844b040000" for 127.0.0.1 at 2014-10-14 17:03:04 -0300
Processing by Admin::ImagesController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"hHz3W90KMgGK+LGtjLMGQmx295tvva6IFIcD4gqgG+8=", "image"=>{"title"=>"img 3", "description"=>"", "technique"=>"", "date"=>"", "public"=>"0"}, "commit"=>"Atualizar Image", "portfolio_id"=>"5436dc1c646172844b000000", "portfolio_item_id"=>"5436dc27646172844b010000", "id"=>"5436de41646172844b040000"}
  MOPED: 127.0.0.1:27017 COMMAND      database=admin command={:ismaster=>1} runtime: 1.0710ms
  MOPED: 127.0.0.1:27017 QUERY        database=portfolio_development collection=admins selector={"$query"=>{"_id"=>BSON::ObjectId('4cb5fbc04174a17926000002')}, "$orderby"=>{:_id=>1}} flags=[] limit=-1 skip=0 batch_size=nil fields=nil runtime: 1.0460ms
  MOPED: 127.0.0.1:27017 QUERY        database=portfolio_development collection=portfolios selector={"_id"=>BSON::ObjectId('5436dc1c646172844b000000')} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 2.8700ms
  MOPED: 127.0.0.1:27017 UPDATE       database=portfolio_development collection=portfolios selector={"_id"=>BSON::ObjectId('5436dc1c646172844b000000'), "portfolio_items._id"=>BSON::ObjectId('5436dc27646172844b010000'), "portfolio_items.0.images._id"=>BSON::ObjectId('5436de41646172844b040000')} update={"$set"=>{"portfolio_items.0.images.$.public"=>false}} flags=[]
                         COMMAND      database=portfolio_development command={:getlasterror=>1, :w=>1} runtime: 1.2790ms
Redirected to http://0.0.0.0:3000/admin/portfolios/5436dc1c646172844b000000/portfolio_items/5436dc27646172844b010000/images/5436de41646172844b040000/edit
Completed 302 Found in 26ms

      

I am actually updating another object in the same collection (with, of course, a different ID), namely the first object in the collection.

The controller code is picking the correct objects, this update seems to be creating this mess. Anyone have an idea what I can do about this?

Here's what's going on in my controller, but I can't spot an error there, the correct objects were always selected:

class Admin::ImagesController < Admin::AdminController

  before_filter :find_parents

  def find_parents
    @portfolio = Portfolio.find(params[:portfolio_id])
    @portfolio_item = @portfolio.portfolio_items.find(params[:portfolio_item_id])
    if params[:id]
      @image = @portfolio_item.images.find(params[:id])
    end
  end

  def update
    @image.update_attributes(image_params)
    if @image.valid?
      redirect_to :back
    else
      flash[:error] = t('simple_form.error_notification.default_message')
      render template: 'admin/images/edit'
    end
  end

 def image_params
    params.require(:image).permit(:title, :description, :technique, :date, :image, :public, :delete_image)
 end

end

      

Also I don't get the error.

Here's a console session that shows the behavior pretty clearly.

Loading development environment (Rails 4.1.5)
[1] pry(main)> p = Portfolio.last
=> #<Portfolio _id: 5436dc1c646172844b000000, index: 4, public: true, title: "test portfolio", _slugs: ["test-portfolio"], description: "">
[2] pry(main)> i = p.portfolio_items.first
=> #<PortfolioItem _id: 5436dc27646172844b010000, index: 0, public: true, title: "test item", _slugs: ["test-item"], client: "", description: "", date: nil>
[3] pry(main)> imgs = i.images
=> [#<Image _id: 5436dc40646172844b020000, index: 1, public: false, title: "i was changed", _slugs: ["img-4", "i-was-changed-1"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>, #<Image _id: 5436dc4b646172844b030000, index: 0, public: false, title: "img 2", _slugs: ["img-2"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>, #<Image _id: 5436de41646172844b040000, index: 2, public: true, title: "img 3", _slugs: ["img-3"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>, #<Image _id: 543d7ada6461722ec0010000, index: 3, public: false, title: "img 4", _slugs: ["img-4"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>]
[4] pry(main)> img = imgs[3]
=> #<Image _id: 543d7ada6461722ec0010000, index: 3, public: false, title: "img 4", _slugs: ["img-4"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>
[5] pry(main)> img.title = 'i was changed'
=> "i was changed"
[6] pry(main)> img.save
=> true
[7] pry(main)> img.reload
=> #<Image _id: 543d7ada6461722ec0010000, index: 3, public: false, title: "img 4", _slugs: ["img-4"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>
[8] pry(main)> 
[9] pry(main)> p = p.reload
=> #<Portfolio _id: 5436dc1c646172844b000000, index: 4, public: true, title: "test portfolio", _slugs: ["test-portfolio"], description: "">
[10] pry(main)> i = p.portfolio_items.first
=> #<PortfolioItem _id: 5436dc27646172844b010000, index: 0, public: true, title: "test item", _slugs: ["test-item"], client: "", description: "", date: nil>
[11] pry(main)> imgs = i.images
=> [#<Image _id: 5436dc40646172844b020000, index: 1, public: false, title: "i was changed", _slugs: ["img-4", "i-was-changed"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>, #<Image _id: 5436dc4b646172844b030000, index: 0, public: false, title: "img 2", _slugs: ["img-2"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>, #<Image _id: 5436de41646172844b040000, index: 2, public: true, title: "img 3", _slugs: ["img-3"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>, #<Image _id: 543d7ada6461722ec0010000, index: 3, public: false, title: "img 4", _slugs: ["img-4"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>]
[12] pry(main)> img = imgs[3]
=> #<Image _id: 543d7ada6461722ec0010000, index: 3, public: false, title: "img 4", _slugs: ["img-4"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>
[13] pry(main)> changed = imgs.select {|x| x.title == 'i was changed'}
=> [#<Image _id: 5436dc40646172844b020000, index: 1, public: false, title: "i was changed", _slugs: ["img-4", "i-was-changed"], description: "", technique: "", date: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, image_fingerprint: nil>]
[14] pry(main)> changed = imgs.select {|x| x.title == 'i was changed'}

      

Models:

And for everyone's mind, wtfing pleaseup - tests that don't fail:

test 'the correct image is updated' do
      p = FactoryGirl.create(:portfolio)
      item = FactoryGirl.create(:portfolio_item)
      image1 = FactoryGirl.create(:image)
      image2 = FactoryGirl.create(:image)
      image3 = FactoryGirl.create(:image)
      item.images << image1
      item.images << image2
      item.images << image3
      p.portfolio_items << item
      assert(p.valid?)
      p.save
      pos = 0..2

      pos.each do |i|
        title =  "Hello World #{i}"
        pt= Portfolio.first
        pt.portfolio_items[0].images[i].title = title
        pt.save
        pt.reload

        assert(pt.portfolio_items[0].images[i].title == title)
        pp pt.portfolio_items[0].images.map { |x| x.title }
      end
end

      

+3


source to share


2 answers


So, I just found out that it is a mongoDB bug that will bite me here (why in a webapp and not in a test is a bit unclear to me, but that's a different story). The problem is this: https://jira.mongodb.org/browse/SERVER-831 and the follow-up to update mongodb to 2.6.



+1


source


try it

[6] pry(main)> img.save

      

img.reload



try to reload the model object after manipulation, http://mongoid.org/en/mongoid/docs/querying.html :

label.bands.push(band)

label.bands #=> [ band ]
band.update_attribute(:active, false)
label.bands #=> [ band ] Must reload.
label.reload.bands #=> []

      

0


source







All Articles