Search code examples
rubyvariablesscopeclass-instance-variables

Ruby class variable scope issue


Ok, so I've read up on class variables, class instance variables and instance variables in Ruby. I found this explanation by Phrogz very illuminating.

Now I'm trying to add a variable to my class that is accessible by multiple methods within my class, but that is not shared among multiple instances of the class:

Class QuizSession < ApplicationRecord
  attr_accessor :index_changed
  def initialize
    @index_changed = false
  end

  def index_changed?
    @index_changed
  end

  def set_index_changed!
    @index_changed = false
  end

  def method_a
    do sth.
    ...
    @index_changed = true
  end
end

What I want is this: (like @my_things in Phrogz example)

session_a = QuizSession.new
session_b = QuizSession.new

session_a.method_a

p session_a.index_changed? #=> true
p session_b.index_changed? #=> false

Am I assuming correctly, that currently I'm defining 4 different @index_changed variables, each in the scope of their respective method, but not visible to the rest of the class?

But if I declare the @index_changed variable outside of a method as a class instance variable, won't it be shared among class instances as well?


Solution

  • Am I assuming correctly, that currently I'm defining 4 different @index_changed variables, each in the scope of their respective method, but not visible to the rest of the class?

    No.

    @index_changed is an instance variable. It is an attribute of each instance of the class.

    class Foo
      attr_reader :my_instance_var
      def initialize(val)
        @my_instance_var = val
      end
    end
    
    f1 = Foo.new(true)
    f2 = Foo.new(false)
    
    f1.my_instance_var # => true
    f2.my_instance_var # => false
    

    But if I declare the @index_changed variable outside of a method as a class instance variable, won't it be shared among class instances as well?

    Yes, because in that case you would be declaring a class instance variable. This is different.


    To clarify, your code above is declaring a variable that is "owned by the class instance". So it is accessible within all of the methods, but is not shared between different class instances.

    A class variable, on the other hand, is "owned by the class". So, if you like, it is "shared between all instances".