class_attribute(*attrs) public

Declare a class-level attribute whose value is inheritable by subclasses. Subclasses can change their own value and it will not impact parent class.

class Base class_attribute :setting end class Subclass < Base end Base.setting = true Subclass.setting # => true Subclass.setting = false Subclass.setting # => false Base.setting # => true 

In the above case as long as Subclass does not assign a value to setting by performing Subclass.setting = something , Subclass.setting would read value assigned to parent class. Once Subclass assigns a value then the value assigned by Subclass would be returned.

This matches normal Ruby method inheritance: think of writing an attribute on a subclass as overriding the reader method. However, you need to be aware when using class_attribute with mutable structures as Array or Hash. In such cases, you don’t want to do changes in places but use setters:

Base.setting = [] Base.setting # => [] Subclass.setting # => [] # Appending in child changes both parent and child because it is the same object: Subclass.setting << :foo Base.setting # => [:foo] Subclass.setting # => [:foo] # Use setters to not propagate changes: Base.setting = [] Subclass.setting += [:foo] Base.setting # => [] Subclass.setting # => [:foo] 

For convenience, a query method is defined as well:

Subclass.setting? # => false 

Instances may overwrite the class value in the same way:

Base.setting = true object = Base.new object.setting # => true object.setting = false object.setting # => false Base.setting # => true 

To opt out of the instance writer method, pass :instance_writer => false.

object.setting = false # => NoMethodError
Show source
Register or log in to add new notes.
September 15, 2011
2 thanks

beware of trying to dup in subclass inside class context

The example of adding to an array without effecting superclass:

# Use setters to not propagate changes: Base.setting = [] Subclass.setting += [:foo] 

That’s right as far as it goes. But beware when you are in context of class definition:

class Subclass < Base # possibly wrong, ruby seems to get  # confused and think you mean a local  # var, not the class ivar setting += [:foo] # But this will work: self.setting += [:foo] # Or: self.setting = self.setting.dup self.setting << :foo [...] end
August 20, 2012
0 thanks

To use class attribute with a hash

You can use a setter with merge:

self.settings = settings.merge(key => value)