When developing instance methods in Ruby, one common problem is correctly restoring the object’s state upon method completion.
For example, you need to modify instance variables for only one method call and then return them to their initial state. You could use a simple and obvious solution: save the original value in a temporary variable and then restore it at the end of the method.
However, this will only work until an exception is thrown. Since the variable is not restored at the end of the method, the object’s state will be corrupted. To prevent this, move the variable restoration code to the ensure block, as the code in it is always executed.
class Action
def initialize(n) = (@number = n)
def show = puts(@number)
def with_other_number_wrong(n)
old = @number
@number = n
yield if block_given?
@number = old
end
def with_other_number_right(n)
old = @number
@number = n
yield if block_given?
ensure
@number = old
end
end
Action.new(100).then do |a|
a.show # 100
begin
a.with_other_number_wrong(200) do
a.show # 200
raise 'wrong'
end
rescue StandardError
end
a.show # 200
end
Action.new(100).then do |a|
a.show # 100
begin
a.with_other_number_right(200) do
a.show # 200
raise 'wrong'
end
rescue StandardError
end
a.show # 100
end