Last Updated: June 16, 2016
·
18.85K
· mbillard

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:

3 Responses
Add your response

even better: after_find { readonly! }

over 1 year ago ·

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
over 1 year ago ·

Oh and actually !new_record? is a neater way of writing new_record? ? false : true

over 1 year ago ·