AlexQueue
AlexQueue

Reputation: 6551

Validate that no attributes can be changed

I have an "immutable" class, and it needs to stay that way for logging/accounting purposes.

How do I ensure that no one updates any columns on this model? I have seen https://stackoverflow.com/a/14781183/902907 and it's a great solution for a column-by-column basis, but I want to do this for every column.

I'd like to avoid read_only_attributes because those fail too quietly.

Upvotes: 0

Views: 47

Answers (1)

Matt Brictson
Matt Brictson

Reputation: 11092

How about:

class JournalEntry < ActiveRecord::Base
  before_update { fail ActiveRecord::ReadOnlyRecord }
end

This will allow new journal entries to be created, but if you attempt to save, it will fail.

j = JournalEntry.new
j.amount = "21.85"
j.save
# => true
j.amount = "39.00"
j.save
# => ActiveRecord::ReadOnlyRecord

Alternatively, this approach utilizes the readonly! method provided by ActiveRecord:

class JournalEntry < ActiveRecord::Base
  after_initialize { readonly! if persisted? }
  after_create { readonly! }
end

However, both techniques have a shortcoming: they do not prevent you from mutating the database by using low-level calls. For example, update_column, which bypasses validations and callbacks, will defeat these read-only checks.

Upvotes: 1

Related Questions