There is a class Section
(as part of MyModule
mixin).
Its instance variable @mark
is initialized to nil
, and can be changed by an instance method change_mark
when its current value is nil
, but not when it's been set to something else. I'm trying to build some protections to prevent the instance variable from being set in such case.
Here's what I have:
module MyModule
class Section
attr_accessor :id, :mark
def initialize(id, mark)
@id = id
@mark = mark
end
def change_mark(mark)
if @mark != nil?
message = "Section ##{@id} is already marked. Choose another."
raise RuntimeError.new(message)
else
@mark = mark
end
end
end
end
Is raising an error the simplest way to prevent changes to a previously-set instance variable? If not, what can I do?
If you want to be that super-strict about not letting users reset the variable, then yes, raise/fail is a good way to go. One note, though: use mark=
accessor, so that the users won't have to remember using restrictive change_mark
instead of all-allowing default writer mark=
.
module MyModule
class Section
attr_accessor :id, :mark
def initialize(id, mark)
self.id = id
self.mark = mark
end
# overwrite generated setter from attr_accessor
def mark=(mark)
if !mark.nil?
message = "Section ##{id} is already marked. Choose another."
fail RuntimeError.new(message)
else
@mark = mark
end
end
end
end
Or you could just ignore the new value.
def mark=(mark)
@mark = mark if @mark.nil?
end
This way you won't know which line attempted to reset the value and when. But it's quieter. The choice is yours. :)
I would suggest changing the line:
attr_accessor :id, :mark
To two lines like:
attr_accessor :id
attr_reader :mark
So your mark
can be changed only via change_mark
method, so proper exception is thrown.
With attr_reader :mark
there is only "getter" method created for your attribute, so you don't have to wary about any other way of setting your attribute value.
Good luck!