-
Type: Bug
-
Resolution: Works as Designed
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Associations
-
Labels:None
-
Environment:Ruby on Rails 4, Mongoid 5 (and higher?)
Given:
class Contact include Mongoid::Document has_and_belongs_to_many :businesses end class Business include Mongoid::Document has_and_belongs_to_many :contacts end
Then:
c = Contact.new b = Business.new c.businesses << b
I expect business_ids and contact_ids to be populated, respectively, as so:
=> #<Contact _id: 5d41e9be3ed1491dac000000, business_ids: [BSON::ObjectId('5d41e9c43ed1491dac000001')]> => [#<Business _id: 5d41e9c43ed1491dac000001, contact_ids: [BSON::ObjectId('5d41e9be3ed1491dac000000')]>]
But sometimes contact_ids of the business remains empty. I could not figure out the inconsistency. Why sometimes it worked and why other times it did not. I traced it down to this line of code in many_to_many.rb (delineated here *https://www.rubydoc.info/github/mongoid/mongoid/Mongoid/Relations/Referenced/ManyToMany#%3C%3C-instance_method* ) :
The << aliased as push definitely builds the relationship on the receiver's businesses association method at this line:
base.add_to_set(foreign_key => doc.send(__metadata.primary_key))
In other words, the above code adds the _id of the business object to business_ids of #<Contact instance. But I don't see where it is building the inverse relation, that is, where is it storing the contact _id into the business's contact_ids collection?
This is the whole method:
def <<(*args) docs = args.flatten return concat(docs) if docs.size > 1 if doc = docs.first append(doc) base.add_to_set(foreign_key => doc.send(__metadata.primary_key)) if child_persistable?(doc) doc.save end end unsynced(base, foreign_key) and self end