views:

2718

answers:

3

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?

+5  A: 

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 add's two methods to the class, one which reads the instance variable, and other that set's 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 atribute 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
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
I'ts different, see answer again
krusty.ar
This will only work for class instance variables, b/c attr_* defines methods for instance variables (of some object).
rampion
+4  A: 

Work your way through _why's seeing metaclasses clearly [mirror] - it's very helpful when trying to understand the way ruby's classes and objects work

Martin DeMello
Brilliant article. Thanks. That helps a lot.
pez_dispenser
Seeing metaclasses clearly can be found here http://dannytatom.github.com/metaid/
Jonas Elfström
thanks jonas, i've edited the comment
Martin DeMello
+1  A: 

In Rails (or anywhere you require 'activesupport') you can use

cattr_accessor :name

to get 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/reader/writer functions.

Charles Dale
much easier - didn't know rails offered this. Thanks!
Brian Armstrong