Modules setting values to nil in unprocessed conditional blocks?

Hi everyone. We’re noticing some strange behavior when including
modules in classes. It seems that even if a conditional block is
forced to evaluate as false (and presumably not execute), assignments
in the conditional block are executed and set to nil. Here is an
example:

==========================
module Conundrum
def riddle
@riddle ||= ‘mystery’
end

def riddle=(new_val)
puts “Called riddle=”
@riddle = new_val
end
end

class Test
include Conundrum

def test
puts “Before: #{riddle}”
if true == false
riddle = ‘solved!’
end
puts “After: #{riddle}”
puts “After class: #{riddle.class}”
end
end

Test.new.test

Note that this prints out:

Before: mystery
After:
After class: NilClass

So it would seem that riddle= is not getting called, but yet the
riddle function now returns nil. Interestingly, this fixes the
problem:

==========================
module Conundrum
def riddle
@riddle ||= ‘mystery’
end

def riddle=(new_val)
puts “Called riddle=”
@riddle = new_val
end
end

class Test
include Conundrum

def test
puts “Before: #{riddle}”
if true == false
@riddle = ‘solved!’
end
puts “After: #{riddle}”
puts “After class: #{riddle.class}”
end
end

Test.new.test

Outputs:

Before: mystery
After: mystery
After class: String

Any insights are much appreciated!

-n8

Nate wrote:

Hi everyone. We’re noticing some strange behavior when including
modules in classes. It seems that even if a conditional block is
forced to evaluate as false (and presumably not execute), assignments
in the conditional block are executed and set to nil. Here is an
example:

==========================
module Conundrum
def riddle
@riddle ||= ‘mystery’
end

def riddle=(new_val)
puts “Called riddle=”
@riddle = new_val
end
end

class Test
include Conundrum

def test
puts “Before: #{riddle}”
if true == false

Inside test, self is equal to the Test instance you created here:

Test.new.test

And this line:

puts "Before: #{riddle}"

is equivalent to:

puts "Before: #{self.riddle}"

However, when ruby parses this line:

  riddle = 'solved!'

ruby creates a local variable named riddle. As a result, when you get
to this statement:

puts "After: #{riddle}"

riddle is no longer equivalent to self.riddle. Instead riddle is just
riddle; and riddle is a local variable that hasn’t been assigned a
value. For local variables that exist but have not been assigned a
value, ruby returns nil for the value of the variable. Then the string
interpolation calls nil.to_s which returns a blank string.

7stud – wrote:

However, when ruby parses this line:

  riddle = 'solved!'

ruby creates a local variable named riddle.

Just to clarify: “parse” is different than “execute”. That line will
never execute, but ruby still parses the code; and it’s when ruby parses
the code that the local variable riddle is created.

On Aug 24, 9:14 am, 7stud – [email protected] wrote:

the code that the local variable riddle is created.

Posted viahttp://www.ruby-forum.com/.

Clicked “Reply to Author” accidently earlier but meant to give some
public thanks for your response. So, thanks, appreciate the response
and the precision you provided in your answer.

  • n8 -