-
Type: Task
-
Resolution: Done
-
Affects Version/s: None
-
Component/s: None
Hi,
Following Readonly Attributes I would expect that trying to save a document where I've modified a readonly attribute would fail. It does not.
For example:
class Band include Mongoid::Document field :name, type: String field :origin, type: String attr_readonly :name, :origin end # These fail as documented rails console> band = Band.first rails console> band.update_attribute(:name, "Tool") Mongoid::Errors::ReadonlyAttribute: Problem: Attempted to set the readonly attribute 'name' with the value: Tool. Summary: Attributes flagged as readonly via Model.attr_readonly can only have values set when the document is a new record. Resolution: Don't define 'name' as readonly, or do not attempt to update its value after the document is persisted. from /Users/joel/.rvm/gems/ruby-2.2.2/gems/mongoid-4.0.2/lib/mongoid/persistable/updatable.rb:29:in `update_attribute' ... rails console> band.remove_attribute(:name) Mongoid::Errors::ReadonlyAttribute: Problem: Attempted to set the readonly attribute 'name' with the value: nil. Summary: Attributes flagged as readonly via Model.attr_readonly can only have values set when the document is a new record. Resolution: Don't define 'name' as readonly, or do not attempt to update its value after the document is persisted. from /Users/joel/.rvm/gems/ruby-2.2.2/gems/mongoid-4.0.2/lib/mongoid/attributes.rb:144:in `remove_attribute' # This does not fail, but I would expect it to rails console> band = Band.first rails console> band.name = 'new name' rails console> band.save => true # I would also expect this to fail rails console> band = Band.first rails console> band.name = 'new name' rails console> band.save! => true
Neither save nor save! fail when I try to save after modifying a readonly attribute: save returns true and save! fails to raise an exception, in both cases indicating that the save succeeded. However, if I then re-read the band I just saved, my "new name" value is not there. So save told me that the save succeeded but it didn't, as my changes were not persisted.
This violates the principal of least surprise. update_attributes and save are basically the same - they both modify attributes in the backing store. But update_attributes fails / raises an exception when we try to modify a readonly attribute, whereas save and save! do not.
This is risky because depending on whether we choose update_attributes or save, we may have a subtle bug in business logic and different enforcement of readonly-ness.
So save and save! should fail if we have tried to set a readonly attribute to a new value prior to invoking them.
I'm happy to help with more diagnostics or code changes if needed.
I am using the following versions:
- OS X 10.10.3
- ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin14]
- rails 4.2.1
- mongoid 4.0.2
- mongodb 3.0.2
Thanks!