Issue #13837 has been updated by shevegen (Robert A. Heiler).


I think hanmac already gave the correct answer so there is no point in me adding 
much to it. :)

Note that you could specifically point ruby to call the getter method in the
line hanmac pointed out, rather than using:

    bar = 0 if bar.nil?

You could use:

    bar = 0 if self.bar.nil?

And then the result would change.

I took the liberty to reformat your input, so that other people have
an easier time to copy/paste; the "irb" comments interfere there. I
also commented it a tiny bit to make it more clear.

Even the old pickaxe mentions that ruby may behave slightly unexpected
in regards to assignments and local variables when it comes to nil

    class Foo

      attr_accessor :bar

      def initialize
        self.bar = 1 # Assigned 1 to @bar.
      end

      def hoge
        bar # Call reader method bar().
      end

      def fuga
        bar = 0 if bar.nil?
        [bar, self.bar]
      end

      def baz
        if bar.nil?
          bar = 0
        end
      end

    end

    foo = Foo.new
    p foo.bar
    p foo.hoge
    p foo.fuga
    p foo.bar
    p foo.baz

# Returns:
    1
    1
    [0, 1]
    1
    nil



----------------------------------------
Bug #13837: Class attributes get overshadowed by local variables
https://bugs.ruby-lang.org/issues/13837#change-66266

* Author: valerauko (Balint Erdos)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: 2.4.1
* Backport: 2.2: UNKNOWN, 2.3: UNKNOWN, 2.4: UNKNOWN
----------------------------------------
~~~ ruby
irb(main):001:0> RUBY_VERSION
=> "2.4.1"
irb(main):002:0> class Foo
irb(main):003:1>   attr_accessor :bar
irb(main):004:1>   def initialize
irb(main):005:2>     self.bar = 1
irb(main):006:2>   end
irb(main):007:1>   def baz
irb(main):008:2>     if bar.nil?
irb(main):009:3>       bar = 0
irb(main):010:3>     end
irb(main):011:2>   end
irb(main):012:1>   def fuga
irb(main):013:2>     bar = 0 if bar.nil?
irb(main):014:2>     [bar, self.bar]
irb(main):015:2>   end
irb(main):016:1>   def hoge
irb(main):017:2>     bar
irb(main):018:2>   end
irb(main):019:1> end
=> :hoge
irb(main):020:0> foo = Foo.new
=> #<Foo:0x00564abe333740 @bar=1>
irb(main):021:0> foo.bar
=> 1
irb(main):022:0> foo.hoge
=> 1
irb(main):023:0> foo.fuga
=> [0, 1]
irb(main):024:0> foo.bar
=> 1
irb(main):025:0> foo.baz
=> nil
~~~

Even though the bar.nil? in fuga should not be true, it gets overwritten by the local variable preceding the if and thus evaluates true.
I'd expect a behavior like below. It's really weird to get my class attributes overridden by a local variable that shouldn't even be evaluated.
~~~ ruby
1 if 2.nil?
=> nil
~~~



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>