29

If I have a class with an attr_accessor, it defaults to creating an instance variable along with the corresponding getters and setters. But instead of creating an instance variable, is there a way to get it to create a class variable or a class instance variable instead?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
pez_dispenser
  • 4,394
  • 7
  • 37
  • 47
  • Work your way through "[Seeing Metaclasses Clearly](http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html)"; it's very helpful when trying to understand the way Ruby's classes and objects work. – Martin DeMello May 22 '09 at 06:48

2 Answers2

46

Like this:

class TYourClass
  class << self
    attr_accessor :class_instance_variable
  end
end

You can look at this as opening the metaclass of the class (of which the class itself is an instance) and adding an attribute to it.

attr_accessor is a method of class Class, it adds two methods to the class, one which reads the instance variable, and other that sets it. Here's a possible implementation:

class Class
  def my_attr_accessor(name)
    define_method name do
      instance_variable_get "@#{name}"
    end 
    define_method "#{name}=" do |new_val|
      instance_variable_set "@#{name}", new_val
    end
  end
end

Completely untested class attribute accessor:

class Class
  def class_attr_accessor(name)
    define_method name do
      class_variable_get "@@#{name}"
    end 
    define_method "#{name}=" do |new_val|
      class_variable_set "@@#{name}", new_val
    end
  end
end
krusty.ar
  • 4,015
  • 1
  • 25
  • 28
  • Thanks. I like your way of saying that it opens the metaclass of the class and sorts of adds an addendum. But why does it produce a class instance variable instead of a class variable? And would it be possible to get it to produce a class variable also or would this syntax only work for class instance variables? – pez_dispenser May 21 '09 at 23:28
  • I'ts different, see answer again – krusty.ar May 21 '09 at 23:36
  • This will only work for class instance variables, b/c attr_* defines methods for instance variables (of some object). – rampion May 23 '09 at 04:31
  • 1
    There are some "," missing between arguments to instance_variable_set and class_variable_set but the edit is too small to submit. – Michael Feb 20 '14 at 03:00
21

In Rails, (or anywhere you do require 'active_support') you can use cattr_accessor :name to get the true class variable accessors.

The class instance variables that others have pointed out are usually more useful. The APIdock cattr_accessor page has some helpful discussion clarifying when you would want one not the other, plus the source to the cattr_accessor, cattr_reader and cattr_writer functions.

oxfist
  • 749
  • 6
  • 22
Charles Dale
  • 456
  • 4
  • 5