Last Updated: May 03, 2024
·
17.67K
· lexmag

cattr_accessor vs class_attribute

cattr_accessor

class Base
  cattr_accessor :settings

  # def self.settings
  #   @@settings
  # end

  # def self.settings=(value)
  #   @@settings = value
  # end
end

Class variable have a tendency to wander from class to class. @@settings class variable can be exposed through inheritance tree.

class Subclass < Base
end

> Base.settings = 'foo'
> Subclass.settings # => 'foo'
> Subclass.settings = 'bar'
> Base.settings # => 'bar'

class_attribute

class Base
  class_attribute :settings

  # def self.settings
  #   nil
  # end

  # def self.settings?
  #   !!settings
  # end

  # def self.settings=(value)
  #   # store value in singleton class
  #   # by redefining `settings` method each time
  # end
end

Settings value is inheritable by subclasses. Subclasses can change their own value and it will not impact base class.

class Subclass < Base
end

> Base.settings = 'foo'
> Subclass.settings # => 'foo'
> Subclass.settings = 'bar'
> Base.settings # => 'foo'

1 Response
Add your response

I wonder why they chose such complex way to do class attributes. I've always used instance variables for that:

class Base
  class << self
    attr_accessor :settings
  end
end

class Subclass < Base
end

Subclass.settings # nil
Subclass.settings = 'bar'
Subclass.settings # 'bar'

Base.settings # nil
Base.settings = 'foo'
Base.settings # 'foo'
Subclass.settings # still 'bar'

UPDATE: Checked the docs and figured the difference. The class_attribute is inheritable, instance variable is not. Thanks for the protip, it made me investigate this stuff deeper. :)

over 1 year ago ·