Extends the class object with class and instance accessors for class attributes, just like the native attr* accessors for instance attributes.

Note that unlike class_attribute, if a subclass changes the value then that would also change the value for parent class. Similarly if parent class changes the value then that would change the value of subclasses too.

class Person
  cattr_accessor :hair_colors
end

Person.hair_colors = [:brown, :black, :blonde, :red]
Person.hair_colors     # => [:brown, :black, :blonde, :red]
Person.new.hair_colors # => [:brown, :black, :blonde, :red]

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

class Person
  cattr_accessor :hair_colors, :instance_writer => false, :instance_reader => false
end

Person.new.hair_colors = [:brown]  # => NoMethodError
Person.new.hair_colors             # => NoMethodError
Methods
C
D
S
Instance Public methods
cattr_accessor(*syms, &blk)
# File activesupport/lib/active_support/core_ext/class/attribute_accessors.rb, line 75
def cattr_accessor(*syms, &blk)
  cattr_reader(*syms)
  cattr_writer(*syms, &blk)
end
cattr_reader(*syms)
# File activesupport/lib/active_support/core_ext/class/attribute_accessors.rb, line 28
def cattr_reader(*syms)
  options = syms.extract_options!
  syms.each do |sym|
    class_eval(        unless defined? @@#{sym}          @@#{sym} = nil        end        def self.#{sym}          @@#{sym}        end, __FILE__, __LINE__ + 1)

    unless options[:instance_reader] == false
      class_eval(          def #{sym}            @@#{sym}          end, __FILE__, __LINE__ + 1)
    end
  end
end
cattr_writer(*syms)
# File activesupport/lib/active_support/core_ext/class/attribute_accessors.rb, line 51
def cattr_writer(*syms)
  options = syms.extract_options!
  syms.each do |sym|
    class_eval(        unless defined? @@#{sym}          @@#{sym} = nil        end        def self.#{sym}=(obj)          @@#{sym} = obj        end, __FILE__, __LINE__ + 1)

    unless options[:instance_writer] == false
      class_eval(          def #{sym}=(obj)            @@#{sym} = obj          end, __FILE__, __LINE__ + 1)
    end
    self.send("#{sym}=", yield) if block_given?
  end
end
class_attribute(*attrs)

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 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
# File activesupport/lib/active_support/core_ext/class/attribute.rb, line 68
def class_attribute(*attrs)
  options = attrs.extract_options!
  instance_reader = options.fetch(:instance_reader, true)
  instance_writer = options.fetch(:instance_writer, true)

  attrs.each do |name|
    class_eval         def self.#{name}() nil end        def self.#{name}?() !!#{name} end        def self.#{name}=(val)          singleton_class.class_eval do            remove_possible_method(:#{name})            define_method(:#{name}) { val }          end          if singleton_class?            class_eval do              remove_possible_method(:#{name})              def #{name}                defined?(@#{name}) ? @#{name} : singleton_class.#{name}              end            end          end          val        end        if instance_reader          remove_possible_method :#{name}          def #{name}            defined?(@#{name}) ? @#{name} : self.class.#{name}          end          def #{name}?            !!#{name}          end        end, __FILE__, __LINE__ + 1

    attr_writer name if instance_writer
  end
end
duplicable?()

Classes are not duplicable:

c = Class.new # => #<Class:0x10328fd80>
c.dup         # => #<Class:0x10328fd80>

Note dup returned the same class object.

# File activesupport/lib/active_support/core_ext/object/duplicable.rb, line 91
def duplicable?
  false
end
superclass_delegating_accessor(name, options = {})
# File activesupport/lib/active_support/core_ext/class/delegating_attributes.rb, line 7
def superclass_delegating_accessor(name, options = {})
  # Create private _name and _name= methods that can still be used if the public
  # methods are overridden. This allows
  _superclass_delegating_accessor("_#{name}")

  # Generate the public methods name, name=, and name?
  # These methods dispatch to the private _name, and _name= methods, making them
  # overridable
  singleton_class.send(:define_method, name) { send("_#{name}") }
  singleton_class.send(:define_method, "#{name}?") { !!send("_#{name}") }
  singleton_class.send(:define_method, "#{name}=") { |value| send("_#{name}=", value) }

  # If an instance_reader is needed, generate methods for name and name= on the
  # class itself, so instances will be able to see them
  define_method(name) { send("_#{name}") } if options[:instance_reader] != false
  define_method("#{name}?") { !!send("#{name}") } if options[:instance_reader] != false
end