Ruby ambiguity in methods – why “self.” is important for setters

Take this simple class:

class Thing
  def value
    @value
  end
  
  def value=(new_val)
    @value = new_val
  end
  
  def problem
    puts "value: #{value}"
    
    if false
      value = false
    else
      puts "hello!"
    end
    
    puts "value: #{value}"
  end

  def solution
    puts "value: #{value}"
    
    if false
      self.value = false
    else
      puts "hello!"
    end
    
    puts "value: #{value}"
  end
  
end

…then in the console:

thing = Thing.new
thing.value = true
thing.problem

# Output:
# value: true
# hello!
# value:

thing.solution

# Output:
# value: true
# hello!
# value: true

The only difference between `problem` and `solution` is that in `problem`, I omit the “self.” before the setter. As a result, Ruby decides in the implicit “else” to call something like `value = nil`. This would be really handy if I didn’t already have a setter by the same name. However Ruby finds this ambiguous.

Be careful when leaving “self.” off of setters!!