Inherit class-level instance variables in Ruby?

I want a child class to inherit a class-level instance variable from its parent, but I can’t seem to figure it out. Basically I’m looking for functionality like this:

class Alpha
  class_instance_inheritable_accessor :foo #
  @foo = [1, 2, 3]
end

class Beta < Alpha
  @foo << 4
  def self.bar
    @foo
  end
end

class Delta < Alpha
  @foo << 5
  def self.bar
    @foo
  end
end

class Gamma < Beta
  @foo << 'a'
  def self.bar
    @foo
  end
end

And then I want this to output like this:

> Alpha.bar
# [1, 2, 3]

> Beta.bar
# [1, 2, 3, 4]

> Delta.bar
# [1, 2, 3, 5]

> Gamma.bar
# [1, 2, 3, 4, 'a']

Obviously, this code doesn’t work. Basically I want to define a default value for a class-level instance variables in the parent class, which its subclasses inherit. A change in a subclass will be the default value then for a sub-subclass. I want this all to happen without a change in one class’s value affecting its parent or siblings. Class_inheritable_accessor gives exactly the behavior I want… but for a class variable.

I feel like I might be asking too much. Any ideas?

  • Can rails scopes filter on the number of associated classes for a given field
  • Cancan accessible_by
  • Is there a way to call a private Class method from an instance in Ruby?
  • Module and class variable scope in ruby
  • How can I create a scope in a model that returns only those objects with an associated rank greater than the current_user's rank?
  • Ruby Instance Variables or Local Variables?
  • Rails scopes - undefined methods
  • How do I write this scope to search for attributes on a nested model? (again)
  • 3 Solutions collect form web for “Inherit class-level instance variables in Ruby?”

    Use a mixin:

    module ClassLevelInheritableAttributes
      def self.included(base)
        base.extend(ClassMethods)    
      end
    
      module ClassMethods
        def inheritable_attributes(*args)
          @inheritable_attributes ||= [:inheritable_attributes]
          @inheritable_attributes += args
          args.each do |arg|
            class_eval %(
              class << self; attr_accessor :#{arg} end
            )
          end
          @inheritable_attributes
        end
    
        def inherited(subclass)
          @inheritable_attributes.each do |inheritable_attribute|
            instance_var = "@#{inheritable_attribute}"
            subclass.instance_variable_set(instance_var, instance_variable_get(instance_var))
          end
        end
      end
    end
    

    Including this module in a class, gives it two class methods: inheritable_attributes and inherited.
    The inherited class method works the same as the self.included method in the module shown. Whenever a class that includes this module gets subclassed, it sets a class level instance variable for each of declared class level inheritable instance variables (@inheritable_attributes).

    What I did in my project for using resque is to define a base

    class ResqueBase
      def self.inherited base
        base.instance_variable_set(:@queue, :queuename)
      end
    end
    

    In the other child jobs, the queue instance will be set by default.
    Hope it can help.

    Rails has this built into the framework as a method called class_attribute. You could always check out the source for that method and make your own version or copy it verbatim. The only thing to watch out for is that you don’t change the mutable items in place.

    Ruby is the best programming language in the world - Ruby on Rails.