Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-4520

Set inverse keys on HABTM relationship when subsequently persisting document

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 8.0.1
    • Affects Version/s: 6.3.0
    • Component/s: Associations, Persistence
    • Labels:
      None
    • Minor Change

      Hello,

      Model definitions:

      class Band
        include Mongoid::Document
        has_and_belongs_to_many :tags
      end
      
      class Tag
        include Mongoid::Document
        has_and_belongs_to_many :bands
      end
      

      Test case:

      Band.delete_all
      Tag.delete_all
      
      Band.new.save
      
      t = Tag.new
      t.bands = Band.all
      t.save
      

      After save only band_ids updated with "tags", but no tag_ids added to "bands":

      {"delete"=>"bands", "deletes"=>[{"q"=>{}, "limit"=>0}], "ordered"=>true}
      {"delete"=>"tags", "deletes"=>[{"q"=>{}, "limit"=>0}], "ordered"=>true}
      {"insert"=>"bands", "documents"=>[{"_id"=>BSON::ObjectId('5a939aea4fb9047008c73844')}], "ordered"=>true}
      {"update"=>"bands", "updates"=>[{"q"=>{"$and"=>[{"_id"=>{"$in"=>[]}}]}, "u"=>{"$pull"=>{"tag_ids"=>BSON::ObjectId('5a939aea4fb9047008c73845')}}, "multi"=>true, "upsert"=>false}], "ordered"=>true}
      {"find"=>"bands", "filter"=>{}, "projection"=>{"_id"=>1}, "limit"=>1}
      {"find"=>"bands", "filter"=>{}}
      {"insert"=>"tags", "documents"=>[{"_id"=>BSON::ObjectId('5a939aea4fb9047008c73845'), "band_ids"=>[BSON::ObjectId('5a939aea4fb9047008c73844')]}], "ordered"=>true}
      

      But if save new "tag" before assign "bands" relationship updates properly:

      Band.delete_all
      Tag.delete_all
      
      Band.new.save
      
      t = Tag.new
      t.save
      t.bands = Band.all
      
      {"delete"=>"bands", "deletes"=>[{"q"=>{}, "limit"=>0}], "ordered"=>true}
      {"delete"=>"tags", "deletes"=>[{"q"=>{}, "limit"=>0}], "ordered"=>true}
      {"insert"=>"bands", "documents"=>[{"_id"=>BSON::ObjectId('5a939c4e4fb9047008c73846')}], "ordered"=>true}
      {"insert"=>"tags", "documents"=>[{"_id"=>BSON::ObjectId('5a939c4e4fb9047008c73847')}], "ordered"=>true}
      {"update"=>"bands", "updates"=>[{"q"=>{"$and"=>[{"_id"=>{"$in"=>[]}}]}, "u"=>{"$pull"=>{"tag_ids"=>BSON::ObjectId('5a939c4e4fb9047008c73847')}}, "multi"=>true, "upsert"=>false}], "ordered"=>true}
      {"update"=>"tags", "updates"=>[{"q"=>{"_id"=>BSON::ObjectId('5a939c4e4fb9047008c73847')}, "u"=>{"$set"=>{"band_ids"=>[]}}, "multi"=>false, "upsert"=>false}], "ordered"=>true}
      {"find"=>"bands", "filter"=>{}, "projection"=>{"_id"=>1}, "limit"=>1}
      {"find"=>"bands", "filter"=>{}}
      {"update"=>"tags", "updates"=>[{"q"=>{"_id"=>BSON::ObjectId('5a939c4e4fb9047008c73847')}, "u"=>{"$addToSet"=>{"band_ids"=>{"$each"=>[BSON::ObjectId('5a939c4e4fb9047008c73846')]}}}, "multi"=>false, "upsert"=>false}], "ordered"=>true}
      {"update"=>"bands", "updates"=>[{"q"=>{"_id"=>BSON::ObjectId('5a939c4e4fb9047008c73846')}, "u"=>{"$addToSet"=>{"tag_ids"=>{"$each"=>[BSON::ObjectId('5a939c4e4fb9047008c73847')]}}}, "multi"=>false, "upsert"=>false}], "ordered"=>true}
      

      If replace in first test

      t.bands = Band.all
      

      to

      t.band_ids = Band.all.map{|b|b.id}
      

      we also got correct behavior with "$addToSet"=>{"tag_ids"=>{"$each"=>[BSON::ObjectId..."

      This but is absent in Mongoid 3.1.7

            Assignee:
            neil.shweky@mongodb.com Neil Shweky (Inactive)
            Reporter:
            shovtyuk@gmail.com Dmitry Shovtyuk
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: