tags:

views:

180

answers:

2

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.

+7  A: 

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
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
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
Yes, that is correct.
Logan Capaldo
Ahh, principle of least surprise can be surprising if you're coming from a language that handles this differently ;) Thanks.
Mark A. Nicolosi
A: 

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!”

Mark A. Nicolosi