Ruby Superclass creates a Stack error - ruby

The program below is an attempt to take in an American president, and French President's age, and name. The catch is that the French president says "bein sur" afterward calling his name, age and citizenship (not my idea). I'm having trouble with the French president's catchphrase. Here's my code
class President
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
end
class FrancePresident < President
def self.citizenship
"La France"
end
def initialize(name, age)
super(name, age)
end
def catchphrase
"bien sur"
end
def name
"#{name}, #{catchphrase}"
end
def age
"#{age}, #{catchphrase}"
end
def citizenship
"#{self.class.citizenship}, #{catchphrase}"
end
end
class UnitedStatesPresident < President
def self.citizenship
"The Unites States of America"
end
end
I think I'm referring to the superclass incorrectly because I'm receiving the stack error below.
SystemStackError
stack level too deep
exercise.rb:29
I'm new to Ruby, so any insight will be helpful.

Your name function generates infinite recursion, because it calls itself:
def name
"#{name}, #{catchphrase}" # <-- here, name calls this very function again and again
end
Same goes for age. They should call the instance variables, #name and #age, respectively:
def name
"#{#name}, #{catchphrase}"
end
def age
"#{#age}, #{catchphrase}"
end
Edit
It's probably better still to use super instead of the instance variables, because it makes it clear that you are using the functionality from the base class and adding something to it (Thanks for the tip, tadman!):
def name
"#{super}, #{catchphrase}"
end
def age
"#{super}, #{catchphrase}"
end

Here's the result based on all of your comments. Thanks for all your help!
class President
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
end
class FrancePresident < President
def self.citizenship
"La France"
end
def catchphrase
"bien sur"
end
def name
"#{#name}, #{catchphrase}"
end
def age
"#{#age}, #{catchphrase}"
end
def citizenship
"#{self.class.citizenship}, #{catchphrase}"
end
end
class UnitedStatesPresident < President
def self.citizenship
"The Unites States of America"
end
end

Related

Passing an object from one class to another

Here's code that works but I'm looking to make it as clean as possible, to get the output without having to build a hash.
class Person
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
def create
Report.create({name: #name, age: #age})
end
end
class Report < Person
def self.create(attributes)
puts "Hello, this is my report. I am #{attributes[:name]} and my age is #{attributes[:age]}."
end
end
me = Person.new("Andy", 34)
me.create # Hello, this is my report. I am Andy and my age is 34.
Here are my changes that didn't work, but is there a method that would?
def create
Report.create
end
and
def self.create(attributes)
puts "Hello, this is my report. I am #{:name} and my age is #{:age}."
end
but the output was "I am name and my age is age."
You could just pass the person, something like this:
class Person
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
def report
Report.new(self)
end
end
class Report
attr_accessor :person
def initialize(person)
#person = person
end
def to_s
"Hello, this is my report. I am #{person.name} and my age is #{person.age}."
end
end
me = Person.new("Andy", 34)
puts me.report
# Hello, this is my report. I am Andy and my age is 34.
Note that I've changed some details:
Report doesn't inherit from Person
Report instances are created via new
Person#create is now Person#report
Report uses to_s for the output (which is called by puts)

Trying to figure out what's wrong with this code

I can't come up with a solution.
class Person
def initialize(name)
#name = name
end
def greet(other_name)
#other_name
print "Hi #{#other_name}, my name is #{#name}"
end
end
kit = Person.new("Tom", "Jerry")
kit.greet
I would appreciate a helping hand.
You have to make a decision:
Do you want to provide both names when initializing the Person:
class Person
def initialize(name, other)
#name = name
#other = other
end
def greet
puts "Hi #{#other}, my name is #{#name}"
end
end
kit = Person.new("Tom", "Jerry")
kit.greet
#=> Hi Jerry, my name is Tom
Or do you want to provide the second name when calling the greet method:
class Person
def initialize(name)
#name = name
end
def greet(other)
puts "Hi #{other}, my name is #{#name}"
end
end
kit = Person.new("Tom")
kit.greet("Jerry")
#=> Hi Jerry, my name is Tom
In the initialize method, you should take in two parameters, because you are calling it with two. You were declaring the #other_name variable inside the greet function instead of the initialize one.
This will work.
class Person
def initialize(name, other_name)
#name = name
#other_name = other_name
end
def greet
print "Hi #{#other_name}, my name is #{#name}"
end
end
kit = Person.new("Tom", "Jerry")
kit.greet
https://repl.it/C5wn
Consider writing your code like this:
class Person
attr_reader :name
def initialize(name)
#name = name
end
def greet(person)
puts "Hi #{person.name}, my name is #{name}"
end
end
tom = Person.new("Tom")
jer = Person.new("Jerry")
tom.greet(jer) #=> Hi Jerry, my name is Tom.
This way you actually have another person as an object instead of just a name.

Stack Level Too Deep, Modules and Classes

I am new to Stackoverflow and I am having some trouble on a coding challenge. I need to be able to output the president's age, name, citizenship, along with a catchphrase. I keep receiving the error,
stack level too deep
exercise.rb:12
Can anyone explain, what is wrong? What does the stack level too deep mean?
module Presidential
attr_accessor :name, :age, :citizenship
def initialize(name, age)
#name, #age, #citizenship = name, age, self.class.citizenship
end
end
class FrancePresident
include Presidential
def citizenship
"#{self.citizenship}, #{catchphrase}"
end
def name
"#{name}, #{catchphrase}"
end
def age
"#{age}, #{catchphrase}"
end
def catchphrase
"bien sur"
end
def self.citizenship
"La France"
end
end
Spec:
describe FrancePresident do
describe "catchphrase" do
it "sounds just right" do
expect( FrancePresident.citizenship ).to eq("La France")
sarcozy = FrancePresident.new("Nicolas Sarkozy", 59)
expect( sarcozy.citizenship ).to eq("La France, bien sur")
expect( sarcozy.age ).to eq("59, bien sur")
expect( sarcozy.name ).to eq("Nicolas Sarkozy, bien sur")
end
end
describe "inheritance" do
it "should not inherit from President" do
expect( FrancePresident.superclass.to_s ).not_to eq('President')
end
end
end
Basically Ruby keeps a stack of things waiting for something, and it is getting too large:
class FrancePresident
def citizenship
self.citizenship
end
end
sarkozy = FrancePresident.new
sarkozy.citizenship
When the citizenship method is called, Ruby executes it. The execution is: call the citizenship method. Ruby does this about 10000 times before giving up.
Maybe you can add line numbers to your question, this would make it easier to get the exact line nr. 12 from your error.. but what i can see so far is following:
def citizenship
"#{self.citizenship}, #{catchphrase}"
end
You are calling the method "citizenship" on your instance method "citizenship"..this will end in an stack level to deep, because you call the same method inside the method itself.. I can see that you have a class method "citizenship". You must edit your instance method citizenship like following:
def citizenship
"#{FrancePresident.citizenship}, #{catchphrase}"
end
or
def citizenship
"#{self.class.citizenship}, #{catchphrase}"
end
and your instance method "citizenship" will be save. Within the scope of your instance method "citizenship" the "self" is the instance and not the class. Outside of the instance "self" is the class.
if you fix this like I said you will get your next errors on the "name" and "age" instance method...because of the same raison..
I was getting the same error, the solution lies in NOT accessing the name and age variables from the Presidential module, but from the FrancePresident class itself.
class FrancePresident
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
Then you call the instance variable #

Basic Ruby class - correct code so it returns expected value

Extremely basic, yet I can't figure it out! Noob issues - I have tried several different answers for this, and I am still getting argument errors. Can someone please help enlighten me on the correct answer?
Correct this code, so that the greet function returns the expected value.
class Person
def initialize(name)
#name = name
end
def greet(other_name)
"Hi #{other_name}, my name is #{name}"
end
end
class Person
def initialize(name)
#name = name
end
def greet(other_name)
"Hi #{other_name}, my name is #{#name}"
end
end
You need to access your instance variables by prefixing the variable name with #. Just the same way as when you assigned it.
name is not available in greet. You can either use #name, or add an accessor:
class Person
def initialize(name)
#name = name
end
def greet(other_name)
"Hi #{other_name}, my name is #{#name}"
end
end
or
class Person
attr_accessor :name
def initialize(name)
#name = name
end
def greet(other_name)
"Hi #{other_name}, my name is #{name}"
end
end

Ruby class set/get

What is wrong with this set/get?
class Pupil
def name
#name
end
def name=(name)
#name = name
end
def age
#age
end
def age=(age)
#age
end
end
Further on the same, if there was a child class with 3 arguments, name, age, sex, would the set get method in the child for sex only. Can you please show the set/get method and initialize in the child class.
def age=(age)
#age
end
should be
def age=(age)
#age = age
end
You can also make your code beautiful by replacing get/set with attr_accessor which itself provides a getter/setter
class Pupil
attr_accessor :age,:name
end
You forgot to set #age = age.

Resources