Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix MONGOID-4874 Values seem to be lost when using add_to_set on a non-existent attribute on a loaded instance #4749

Merged

Conversation

jklina
Copy link
Contributor

@jklina jklina commented Apr 24, 2020

It seems when an instance is loaded from a database, its attributes
method returns an instance of BSON::Document. This causes some
surprising behavior when we use #add_to_set on that loaded instance.

When a value is assigned to a BSON::Document instance, it gets
modified:

https://github.com/mongodb/bson-ruby/blob/master/lib/bson/document.rb#L87-L89

During modification, the attribute loses its reference to the original
value, however the add_to_set method relies on this reference:

existing = send(field) || (attributes[field] ||= [])
values = [ value ].flatten(1)
values.each do |val|
existing.push(val) unless existing.include?(val)
end

Since that reference is broken, it no longer update the instance's
attribute and the value is lost in memory, though still retained in the
DB.

This ensures that the reference remains intact.

It seems when an instance is loaded from a database, its `attributes`
method returns an instance of `BSON::Document`. This causes some
surprising behavior when we use `#add_to_set` on that loaded instance.

It seems when a value is assigned to a `BSON::Document` instance, it gets
modified:

https://github.com/mongodb/bson-ruby/blob/master/lib/bson/document.rb#L87-L89

During modification, the attribute loses its reference to the original
value, however the `add_to_set` method relies on this reference:

https://github.com/mongodb/mongoid/blob/136ccbc140b25719f48ff5185bb471f90c063148/lib/mongoid/persistable/pushable.rb#L27-L31

Since that reference is broken, it no longer update the instance's
attribute and the value is lost in memory, though still retained in the
DB.

This ensures that the reference remains intact.
@p-mongo
Copy link
Contributor

p-mongo commented Apr 28, 2020

@p-mongo p-mongo changed the title Retain values added to sets of loaded instances Fix MONGOID-4874 Values seem to be lost when using add_to_set on a non-existent attribute on a loaded instance Apr 28, 2020
@p-mongo p-mongo requested a review from egiurleo April 29, 2020 01:33
@p-mongo p-mongo merged commit edfe855 into mongodb:master Apr 29, 2020
p-mongo pushed a commit that referenced this pull request Apr 29, 2020
…n-existent attribute on a loaded instance (#4749)

* Retain values added to sets of loaded instances

It seems when an instance is loaded from a database, its `attributes`
method returns an instance of `BSON::Document`. This causes some
surprising behavior when we use `#add_to_set` on that loaded instance.

It seems when a value is assigned to a `BSON::Document` instance, it gets
modified:

https://github.com/mongodb/bson-ruby/blob/master/lib/bson/document.rb#L87-L89

During modification, the attribute loses its reference to the original
value, however the `add_to_set` method relies on this reference:

https://github.com/mongodb/mongoid/blob/136ccbc140b25719f48ff5185bb471f90c063148/lib/mongoid/persistable/pushable.rb#L27-L31

Since that reference is broken, it no longer update the instance's
attribute and the value is lost in memory, though still retained in the
DB.

This ensures that the reference remains intact.

* expand test coverage

* express the requirements more strictly

Co-authored-by: Oleg Pudeyev <oleg@bsdpower.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants