class_attribute
- 1.0.0
- 1.1.6
- 1.2.6
- 2.0.3
- 2.1.0
- 2.2.1
- 2.3.8
- 3.0.0 (0)
- 3.0.9 (-7)
- 3.1.0 (12)
- 3.2.1 (0)
- 3.2.8 (0)
- 3.2.13 (0)
- 4.0.2 (11)
- 4.1.8 (0)
- 4.2.1 (0)
- 4.2.7 (0)
- 4.2.9 (0)
- 5.0.0.1 (0)
- 5.1.7 (0)
- 5.2.3 (38)
- 6.0.0 (0)
- 6.1.3.1 (0)
- 6.1.7.7 (0)
- 7.0.0 (0)
- 7.1.3.2 (0)
- 7.1.3.4 (0)
- What's this?
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 place. Instead 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, an instance predicate method is defined as well. To skip it, pass instance_predicate: false.
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 reader method, pass instance_reader: false.
object.setting # => NoMethodError object.setting? # => NoMethodError
To opt out of the instance writer method, pass instance_writer: false.
object.setting = false # => NoMethodError
To opt out of both instance methods, pass instance_accessor: false.
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
To use class attribute with a hash
You can use a setter with merge:
self.settings = settings.merge(key => value)