-
Type: Task
-
Resolution: Done
-
Affects Version/s: None
-
Component/s: None
-
None
Current behavior: initialize a new object on read
Right now, specifying a custom field type with
: MyType
calls the
every time the attribute is read, which initializes a new object for the field. So you get unexpected behavior:
class Post
field :author, type: Author
end
post = Post.first
post.author.name = "new name"
post.author.name # < — changes would be lost because the second call to 'post.author' instantiates a new object!
I don't think I'm the only one who found this surprising: see https://github.com/mongoid/mongoid/issues/1604#issuecomment-3547128
and https://github.com/mongoid/mongoid/issues/2951.
Current work around (inconvenient)
There's a solution, which is to assign the field object on the first time and then manipulate that local variable:
post = Post.first
author = post.author
author.name = "new name"
post.save
But this is fairly inconvenient, and if you forget to do so, you can find yourself wondering why changes aren't saved.
Proposed work-around
I hacked together a solution that basically memoizes the object returned from demongoize, and the getter and setter created by field would first look to see if an object is already in memory.
This works alright, but I wanted to see if there's work being done on this, or if there's a better way to handle things I'm completely missing. I'd be happy to take a stab at putting together a more robust solution.
- is related to
-
MONGOID-2951 Attributes of container types are not persisted when mutated
- Backlog
-
MONGOID-4903 Custom fields are instantiated on every access, leading to very unexpected behaviours
- Closed