4

I am trying to get call one of my classes attribute writers, but for some reason it never gets called. Here's some code that'll make this clearer:

class Test
  attr_reader :test

  def test=(val)
    puts 'Called'
    @test = val
  end

  def set_it(val)
    test = val
  end
end

obj = Test.new
obj.set_it 5
puts obj.test
=> nil

The puts statement at the end outputs 'nil'. Adding a debugging statement to test= shows it is never called. What am I doing wrong?

Update

I re-wrote this question partially, as I didn't truly understand the problem when I wrote it. So the question is much more generalized now.

Mark A. Nicolosi
  • 82,413
  • 11
  • 44
  • 46

2 Answers2

8

You're doing nothing "wrong" per se. Ruby just thinks you intend to set the local variable test to val, not call the test= method. self.test = val will do what you expect.

Logan Capaldo
  • 39,555
  • 5
  • 63
  • 78
  • I thought it was something like that. I tried test=(val) thinking that may convince Ruby I'm trying to call a method. Thanks! – Mark A. Nicolosi Feb 23 '09 at 03:25
  • So this would be true whether a mixin is involved or not? If there's no receiver specified Ruby assumes you're setting a local variable? Makes sense. – Mark A. Nicolosi Feb 23 '09 at 03:27
  • Ahh, principle of least surprise can be surprising if you're coming from a language that handles this differently ;) Thanks. – Mark A. Nicolosi Feb 23 '09 at 03:57
0

Here's some other resources on this (apparently common) problem:

Another Stack Overflow question: Why do ruby setters need “self.” qualification within the class?

From this guys's blog:

As a Ruby newbie you probably once did race = "hooman" but noticed it didn’t work and said to yourself: “I won’t let this happen to me again. From now on, I’ll prepend self. whenever I’m calling a method!”

Community
  • 1
  • 1
Mark A. Nicolosi
  • 82,413
  • 11
  • 44
  • 46