-
Type: Bug
-
Resolution: Won't Do
-
Priority: Unknown
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
The following case has a problem, take the following class:
class Post include Mongoid::Document field :title, type: String has_one :comment, inverse_of: :post end class Comment include Mongoid::Document field :content, type: String belongs_to :post, inverse_of: :comment, optional: true end
And then we do the following operations:
post = Post.create! comment1 = Comment.create!(content: "Comment 1") comment2 = Comment.create!(content: "Comment 2") post.comment = comment1 post.reload expect(post.comment).to eq(comment1) # works post.comment = comment2 post.reload expect(post.comment).to eq(comment2) # works post.comment = comment1 post.reload expect(post.comment).to eq(comment1) # fails: post.comment returns nil
I have successfully identified the bug here. What's happening is:
- We are setting post.comment to comment1, which populates the post_id on the comment
- We reload, now post.comment does not refer to the same object as comment1
- Assign comment2 to post.comment. Now comment1 is out of sync, since when assigning comment2 to post.comment, it populates the post_id on comment2 and removes the post_id of the original comment. However, since post.comment no longer refers to the same object as comment1, comment1 still has the post_id populated, while in the database its post_id is nil. Note that this problem disappears and the test passes if you reload the comment.
- Reassign comment1. During this operation, we try to update comment1 with the post_id, since it's post_id should be nil, and when we try to persist the operation, mongoid sees no changes made to the document and doesn't persist it.
To reiterate, the problem arises when you try to assign to a has_one relationship with the correct foreign key already (and prematurely) assigned to the object. This can happen in two ways, in the case described above, and in that case where you try to set the same object to the has_one multiple times. The second case is MONGOID-4646.
- is related to
-
MONGOID-4646 has_one - belongs_to with optional:true incorrectly clears association when assigned itself
- Closed