Somar Melkhem
Somar Melkhem

Reputation: 238

Strange behave of ruby attr_accessor

I have this block of code:

class CallMe
  attr_accessor :a, :b, :c

  def self.start(*args)
     self.new(*args).get_answer
  end

  def initialize(a,b,c)
    @a = a
    @b = b
    @c = c
  end

  def get_answer 
    if c
      b = nil
    else
      return b 
    end
   end
end
answer = CallMe.start(1,2,nil)

Why when i run it in irb i always get answer = nil even logic case is get b value that is 2

Upvotes: 4

Views: 184

Answers (2)

Pavel Mikhailyuk
Pavel Mikhailyuk

Reputation: 2877

Variable Hoisting effect is used in many languages. For Ruby it is described in the official documentation:

The local variable is created when the parser encounters the assignment, not when the assignment occurs

So, get_answer method creates local variable b regardless to value of c. And assigns local variable b to nil while creating. Then get_answer returns local variable b which is always nil.

Correct method:

def get_answer
  c ? self.b = nil : b
end

Upvotes: 3

nattfodd
nattfodd

Reputation: 1900

That's because in context of if statement you actually redefine b when you type b = nil. For Ruby, it's not clear either you want to call object's method :b or to create a new variable b. In such cases, priority always goes from the global to the closest context, in this case - to context inside of if block.

If you'll change

if c
  b = nil
else
  return b
end

# to 
if c
  # b = nil
  # or
  self.b = nil
else
  return b

You'll notice it works as you expected.

Upvotes: 0

Related Questions