Prevent updates on Rails models
Sometimes you want to have a specific model to never change. Here are your options depending on what you need.
To prevent any update on the objects, you simply have to override the readonly?
method in the model:
def readonly?
# allow the creation, you can also use a more complex condition to allow updates under certain conditions
new_record? ? false : true
end
If you also want to prevent the object from being destroyed, add this callback:
before_destroy { |record| raise ReadOnlyRecord }
To prevent only individual attributes from being modified:
attr_readonly :name, :email, :price # ...and so on
Finally, if you want to make an association return readonly objects all the time, you can simply add the readonly: true
option to the association:
belongs_to :parent, readonly: true
has_one :friend, readonly: true
has_many :siblings, readonly: true
has_and_belongs_to_many :groups, readonly: true
Note that if the returned object(s) itself has not implemented any of the above read only options, there's no way of preventing the developer from retrieving a writable instance.
Sources:
Written by Michel Billard
Related protips
3 Responses
even better: after_find { readonly! }
This was really helpful. However, I found that the default behaviour of just the readonly?
override example here was to prevent destroy
.
Here's the approach I took to re-enabling it whilst also making a side-route to explicitly allow an update
before_destroy :allow_next_update!
def allow_next_update!
@allow_update = true
end
def readonly?
if @allow_update
@allow_update = false
return false
end
return true unless new_record?
end
Oh and actually !new_record?
is a neater way of writing new_record? ? false : true