Like a lot of things in Ruby there is no "final", things are inherently dynamic and absolutely preventing people from doing things is never really going to happen. You can just make it difficult.
The one thing to note is in Ruby there's a difference between immutable and constant. A constant is a variable which will generate a warning when reassigned, that's all, and there's nothing to prevent you from modifying it. To prevent modifications you must "freeze" the object in question, though as with all things in Ruby, this is just a request that can be ignored by the object.
Typically you'll see code like this:
ADMIN_USER_TYPE = 'Admin'.freeze
Or this:
USER_TYPES = %w[
Admin
].freeze
The freeze
call is to catch cases where the list might be mangled by some method by accident. It does not absolutely prevent this, it's more of a safety measure. Consider this code:
def user_labels(types)
types.map! { |t| [ t, t.downcase.to_sym ] }
end
Here a mistaken map!
call would have the effect of rewriting the original array. In cases where you're calling it with a throw-away argument this is fine:
user_labels(%w[ Admin Test ])
When you're using the constant you'll permanently modify it, and that will cause it to get modified over and over each time it's called, creating a mess. The freeze
flag trips a warning here and prevents that.
So the short answer is: No. The long answer is you have to be disciplined, the language will not prevent you from doing this if you're sufficiently determined. Pay attention to warnings and treat them seriously.