Featured image

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