Attr_accessor on class variables

Ruby

Ruby Problem Overview


attr_accessor does not work on the following code. The error says "undefined method 'things' for Parent:Class (NoMethodError)":

class Parent
  @@things = []
  attr_accessor :things
end
Parent.things << :car

p Parent.things

However the following code works

class Parent
  @@things = []
  def self.things
    @@things
  end
  def things
    @@things
  end
end
Parent.things << :car

p Parent.things

Ruby Solutions


Solution 1 - Ruby

attr_accessor defines accessor methods for an instance. If you want class level auto-generated accessors you could use it on the metaclass

class Parent
  @things = []

  class << self
    attr_accessor :things
  end
end

Parent.things #=> []
Parent.things << :car
Parent.things #=> [:car]

but note that this creates a class level instance variable not a class variable. This is likely what you want anyway, as class variables behave differently than you might expect when dealing w/ inheritance. See "Class and Instance Variables In Ruby".

Solution 2 - Ruby

attr_accessor generates accessors for instance variables. Class variables in Ruby are a very different thing, and they are usually not what you want. What you probably want here is a class instance variable. You can use attr_accessor with class instance variables like so:

class Something
  class <<self
    attr_accessor :things
  end
end

Then you can write Something.things = 12 and it will work.

Solution 3 - Ruby

Just some clarification: class variables won't be accessible using attr_accessor. It's all about instance variables:

class SomeClass
  class << self
    attr_accessor :things
  end
  @things = []
end

because in Ruby, class is an instance of the class "Class" (God, I love to say that) and attr_accessor sets accessor methods for instance variables.

Solution 4 - Ruby

This is probably the simplest way.

class Parent
  def self.things
    @@things ||= []
  end
end
Parent.things << :car

p Parent.things

Solution 5 - Ruby

Аlso note that a singleton method is a method only for a single object. In Ruby, a Class is also an object, so it too can have singleton methods! So be aware of when you might be calling them.

Example:

class SomeClass
  class << self
    def test
    end
  end
end

test_obj = SomeClass.new

def test_obj.test_2
end

class << test_obj
  def test_3
  end
end

puts "Singleton methods of SomeClass"
puts SomeClass.singleton_methods
puts '------------------------------------------'
puts "Singleton methods of test_obj"
puts test_obj.singleton_methods

Singleton methods of SomeClass

test


Singleton methods of test_obj

test_2

test_3

Solution 6 - Ruby

Parent.class_variable_get(:@@things)

That would be the built-in way. In most cases this should be sufficient I think. No need to have a class variable accessor in the instance.

Solution 7 - Ruby

class Parent
  @things = []
  
  singleton_class.send(:attr_accessor, :things)
end

This pattern is most useful when you are defining accessors dynamically or creating them inside a method:

class Foo
  def self.add_accessor(name)
    singleton_class.send(:attr_accessor, name)
  end
end

Foo.add_accessor :things
Foo.things = [:car]
Foo.things # => [:car]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTalespin_KitView Question on Stackoverflow
Solution 1 - RubyAlex.BullardView Answer on Stackoverflow
Solution 2 - RubyChuckView Answer on Stackoverflow
Solution 3 - RubyVlad KhomichView Answer on Stackoverflow
Solution 4 - RubyPaul ByrneView Answer on Stackoverflow
Solution 5 - RubyartamonovdevView Answer on Stackoverflow
Solution 6 - Rubysu_liView Answer on Stackoverflow
Solution 7 - RubySajad RastegarView Answer on Stackoverflow