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