In Rails, we can mark certain attributes of a model as readonly using the attr_readonly
method. Once an attribute is marked as readonly, it cannot be changed after the record is created.
class User < ActiveRecord::Base
attr_readonly :email
end
Before
If we try to assign a new value to a readonly attribute, the assignment operation would appear to succeed, but the change would not be persisted to the database.
user = User.create!(email: "[email protected]")
user.email # => "[email protected]"
user.email = "[email protected]" # allows assignment
user.email # => "[email protected]"
user.save! # change to email won't be persisted to database
user.reload.email # =>"[email protected]"
After
Rails 7.1 now raises an ActiveRecord::ReadonlyAttributeError on assignment to readonly attributes
This explicit ActiveRecord::ReadonlyAttributeError
error makes it clear that we are trying to modify an attribute that should not be changed, preventing the silent failure in previous versions that could lead to false positives.
user = User.create!(email: "[email protected]")
user.email # => "[email protected]"
user.email = "[email protected]"
# => Raises ActiveRecord::ReadonlyAttributeError
user.update!(email: "[email protected]" )
# => Raises ActiveRecord::ReadonlyAttributeError
Rails 7.1 introduces a configuration option to control readonly attribute behavior and it is enabled by default with load_defaults 7.1
.
# application.rb
config.active_record.raise_on_assign_to_attr_readonly = true
To retain the old behavior we can simply disable it.
# application.rb
config.active_record.raise_on_assign_to_attr_readonly = false