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

HABTM relations behave as one-sided for some actions

    • Type: Icon: Task Task
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 5.1.0
    • Affects Version/s: None
    • Component/s: None
    • None

      Setup

      • Ruby 2.0.0-p247
      • Rails 4
      • Mongoid pointing to master ref cff94429
      • IdentityMap on
      • Pre-load models true

      In app/models create the following two files:

      # band.rb
      class Band
        include Mongoid::Document
      
        field :n, type: String, as: :name
      
        # This seems to be necessary in order to have short relation
        # columns with aliases (similar to the above def)
        has_and_belongs_to_many :tags,
          foreign_key: :t_ids,
          inverse_of: 'b',
          inverse_class_name: 'Tag'
      end
      
      # tag.rb
      class Tag
        include Mongoid::Document
      
        field :n, type: String, as: :name
      
        has_and_belongs_to_many :bands,
          foreign_key: :b_ids,
          inverse_of: 't',
          inverse_class_name: 'Band'
      end
      

      Issue

      Run rails console:

      b1 = Band.create name: 'Foo'
      # MOPED: 127.0.0.1:27017 INSERT       database=development collection=bands documents=[{"_id"=>"5220dfe44984b96f87000001", "n"=>"Foo"}] flags=[] (0.2840ms)
      # => #<Band _id: 5220dfe44984b96f87000001, n(name): "Foo", t_ids: nil>
      
      b2 = Band.create name: 'Bar'
      # MOPED: 127.0.0.1:27017 INSERT       database=development collection=bands documents=[{"_id"=>"5220dfe74984b96f87000002", "n"=>"Bar"}] flags=[] (0.1979ms)
      # => #<Band _id: 5220dfe74984b96f87000002, n(name): "Bar", t_ids: nil>
      
      t1 = Tag.create name: 'Rock'
      # MOPED: 127.0.0.1:27017 INSERT       database=development collection=tags documents=[{"_id"=>"5220e00f4984b96f87000003", "n"=>"Rock"}] flags=[] (0.2429ms)
      # => #<Tag _id: 5220e00f4984b96f87000003, n(name): "Rock", b_ids: nil>
      
      t2 = Tag.create name: 'Soul'
      # MOPED: 127.0.0.1:27017 INSERT       database=development collection=tags documents=[{"_id"=>"5220e0174984b96f87000004", "n"=>"Soul"}] flags=[] (0.2277ms)
      # => #<Tag _id: 5220e0174984b96f87000004, n(name): "Soul", b_ids: nil>
      
      
      # In this instance, adding a tag to a band runs updates for **both**
      b1.tags << t1
      # MOPED: 127.0.0.1:27017 UPDATE       database=development collection=bands selector={"_id"=>"5220dfe44984b96f87000001"} update={"$addToSet"=>{"t_ids"=>{"$each"=>["5220e00f4984b96f87000003"]}}} flags=[] (0.3152ms)
      # MOPED: 127.0.0.1:27017 UPDATE       database=development collection=tags selector={"_id"=>"5220e00f4984b96f87000003"} update={"$addToSet"=>{"b_ids"=>{"$each"=>["5220dfe44984b96f87000001"]}}} flags=[] (0.2391ms)
      # => [#<Tag _id: 5220e00f4984b96f87000003, n(name): "Rock", b_ids: ["5220dfe44984b96f87000001"]>]
      
      
      # ISSUE: Adding a band to a tag, only runs an update for **the tag only**
      t2.bands << b2
      # MOPED: 127.0.0.1:27017 UPDATE       database=development collection=tags selector={"_id"=>"5220e0174984b96f87000004"} update={"$addToSet"=>{"b_ids"=>{"$each"=>["5220dfe74984b96f87000002"]}}} flags=[] (0.2179ms)
      # => [#<Band _id: 5220dfe74984b96f87000002, n(name): "Bar", t_ids: nil>]
      

            Assignee:
            durran.jordan@mongodb.com Durran Jordan
            Reporter:
            cupakromer cupakromer
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: