Reputation:
I'm trying to replicate the functionality of Sinatra. Specifically the DSL-like part where you can define routes in the definition of the class. When I try to run my version of a persons-DSL I get the error, undefined method '<<' for nil:NilClass
on line 11.
class Persons
class << self
def reset!
@persons = []
end
def add_person title, name
@persons << {
title: title,
name: name
}
end
end
reset!
end
class MyPersons < Persons
add_person 'Dr.', 'Bob'
add_person 'Mr.', 'Jones'
end
Upvotes: 0
Views: 413
Reputation:
After a good nights sleep and some more Googling, I have come up with the answer. There appears to be a #inherited
method in Ruby; that is called when a class is inherited (duh).
Actually, this is how Sinatra implements instance variables in Sinatra::Base
.
class Persons
class << self
def reset!
@persons = []
end
def add_person title, name
@persons << {
title: title,
name: name
}
end
def inherited child
child.reset!
end
end
end
class MyPersons < Persons
add_person 'Dr.', 'Bob'
add_person 'Mr.', 'Jones'
end
Upvotes: 0
Reputation: 7934
You are never initializing @persons
to anything other than nil. A simple fix would be
class MyPersons < Persons
reset!
add_person 'Dr.', 'Bob'
add_person 'Mr.', 'Jones'
end
The reason your call to reset!
doesn't work is because MyPersons
and Persons
do not share the same @persons
variable.
You can use @@persons
instead to share the variable. Your example would look like this instead:
class Persons
@@persons = []
class << self
def reset!
@@persons = []
end
def add_person title, name
@@persons << { title: title, name: name }
end
end
end
class MyPersons < Persons
add_person 'Dr.', 'Bob'
add_person 'Mr.', 'Jones'
end
Upvotes: 1