1

I'm trying to use an attr_accessor from inside the class where it is defined, to no avail. Why does this not work?

I would expect the following to output "new" in IRB:

irb(main):016:0> foo = StringClass.new
=> #<StringClass:0x2fbf2c0 @thing="old">
irb(main):017:0> foo.output
old
=> nil
irb(main):018:0> foo.change
=> "new"
irb(main):021:0> foo.output
old
=> nil

Here's the implementation:

class StringClass
  def initialize
    @thing = "old"
  end

  attr_accessor :thing

  def output
    puts thing
  end

  def change
    thing = "new"
  end
end

I can see that the thing= method is defined. I don't understand why that method is not being called when I try changing the value.

DeejUK
  • 12,891
  • 19
  • 89
  • 169
  • Thanks, you're right this is a duplicate. How best to resolve? – DeejUK Jun 15 '15 at 12:01
  • Since you are only referencing the instance variable from within the class, maybe it is better to dispense with the attr_accessor and simply use the @ symbol. – drlolly Apr 09 '21 at 11:28

2 Answers2

2

That is, because those methods should be called with self:

class StringClass
  def initialize
    @thing = "old"
  end

  attr_accessor :thing

  def output
    puts self.thing
  end

  def change
    self.thing = "new"
  end
end
maicher
  • 2,625
  • 2
  • 16
  • 27
  • Thanks. I really don't understand why though, when one doesn't have to do that for methods defined 'normally'. – DeejUK Jun 15 '15 at 11:59
  • 1
    @Deejay - with syntaxt "without" `self`, Ruby doesn't know if you're trying to call a method (you know it, because you understand the context), or just want to create a local variable. If you don't specify `self` - it'll create a local variable in this case – Paweł Dawczak Jun 15 '15 at 12:03
1

Try this -

class StringClass
   ......

   def change
     self.thing = "new"
   end
 end
  1. foo = StringClass.new
  2. foo.change => "new"
Amit Suroliya
  • 1,515
  • 1
  • 11
  • 21