Foo.val return nil instead of "foo" before calling Foo.set?@val on class evaluation?In which scope is @val  = "foo" stored into?
class Foo
  class << self
    @val  = "foo"
    attr_reader :val
    def set(val)
      @val = val
    end
  end
end
p Foo.val # nil
Foo.set("bar")
p Foo.val # "bar"
You can initialize @val in Foo like this:
class Foo
  @val  = "foo"
  class << self
    attr_reader :val
    def set(val)
      @val = val
    end
  end
end
p Foo.val         #=> "foo"
Foo.set("bar")
p Foo.val         #=> "bar"
Your code initializes @val not on Foo, but on Foo's metaclass
Ruby generally executes expressions upon parsing them. The reason why your code did not perform as expected is because you are setting a class instance variable for the singleton class of Foo, but on the other hand you are accessing the class instance variable of Foo itself, that's why it doesn't work:
class << self
  @val  = "foo" # scope is class scope of singleton class of Foo
  attr_reader :val
  def set(val)
    # scope is instance scope of singleton class of Foo (equal to Foo itself)
    @val = val 
  end
end
That's why Foo.val yields nil in your case - it hasn't been set yet.
Setting val on class evaluation can be achieved in the way that Victor already demonstrated.
See also this post for a discussion about scope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With