Reputation: 21877
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
Upvotes: 79
Views: 65648
Reputation: 1
I think what you want is class_attribute
class Base
class_attribute :foo
self.foo = '--UNSET--'
def show
puts self.foo
end
end
class X < Base
self.foo = 'XXX'
end
class Y < Base
self.foo = 'YYY'
end
class Z < Base
end
puts X.foo # -> 'XXX'
puts Y.foo # -> 'YYY'
puts Z.foo # -> '--UNSET--'
X.new.show # -> 'XXX'
X.foo = 'x-x-x'
X.new.show # -> 'x-x-x'
Y.new.show # -> 'YYY'
Upvotes: 0
Reputation: 237010
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.
Upvotes: 19
Reputation: 5563
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".
Upvotes: 119
Reputation: 3154
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]
Upvotes: 1
Reputation: 317
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.
Upvotes: 1
Reputation: 2380
А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
Upvotes: 1
Reputation: 1615
This is probably the simplest way.
class Parent
def self.things
@@things ||= []
end
end
Parent.things << :car
p Parent.things
Upvotes: 5
Reputation: 5880
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.
Upvotes: 5