Passing an object from one class to another - ruby

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)

Related

How do I get the string value in this string interpolation

I've been trying to get this code to output:
'Mary has a pet called Satan.'
But what I get is:
'Mary has a pet called #<Cat:0x00000002784c20>'
Code Below:
class Person
def initialize(name)
#name = name
#pet = nil
#hobbies = []
end
def describe()
puts "This persons name is #{#name}."
puts "#{#name}'s hobbies are:"
#hobbies.map { |hobby| puts hobby }
if #pet == nil
puts "#{#name} has not got any pets."
else
puts "#{#name} has a pet called #{#pet}"
end
end
attr_accessor :pet, :hobbies
end
class Cat < Animal
def initialize(name)
#name = name
end
end
satan = Cat.new("Satan")
mary = Person.new("Mary")
mary.pet = satan
mary.describe
Thanks for all your help.
In your describe() function, you are calling the object Cat without specifing the name.
But if you call #{pet.name} it will throw:
<undefined method `name' for #<Cat:0x0055d750a1a450 #name="Satan">
You have to allow the access to the variable name in the Cat class first with attr_accessor
class Cat < Animal
attr_accessor :name # First allow access
end
class Person
def describe()
puts "#{#name} has a pet called #{#pet.name}" # Then call the pet's name!
end
end

Creating an object from a class which is inherited ruby

Im struggling on understanding (after googling) on how to implement this: I have a class:
class Student
# constructor method
def initialize(name,age)
#name, #age = name, age
end
# accessor methods
def getName
#name
end
def getAge
#age
end
# setter methods
def setName=(value)
#name = value
end
def setAge=(value)
#age = value
end
end
And lets say I have another class which inherits from Student
class Grade < Student
#constructor method
def initialize(grade)
super
#grade = grade
end
# accessor methods
def getGrade
#grade
end
# setter methods
def setGrade=(value)
#grade = value
end
end
I understand how to build an abject:
student = Student.new(name, age)
How can I build this Student (that I have just created) a Grade object associated with the student and how would I call the inherited object, for example i wanted to:
puts 'student name and associated grade'
I know I can place the grade variable within the Student class, but for the purpose of learning im doing it this way.
This code would do what you wanted:
class Grade
attr_accessor :value
def initialize value
#value = value
end
end
class Student
attr_accessor :name, :age, :grade
def initialize name, age, grade
#name, #age, #grade = name, age, Grade.new(grade)
end
end
st = Student.new 'John', 18, 5
puts "student #{st.name} and associated grade #{st.grade.value}"
First off, no need to define accessors in Ruby like that, it's far from idiomatic. Let's clean that up first:
class Student
attr_accessor :name, :age
def initialize(name, age)
#name =name
#age = age
end
end
class Grade
attr_accessor :value
def initialize(grade)
#value = grade
end
end
Secondly it doesn't seem like Grade should inherit from Student at all, just adjust the latter to also store a Grade instance variable:
class Student
attr_accessor :name, :age, :grade
def initialize(name, age, grade = nil)
#name =name
#age = age
#grade = grade
end
end
You can then instantiate a student like this:
student = Student.new("Test", 18, Grade.new(1))
Or because of the default value you leave off the grade and assign it later:
student = Student.new("Test", 18)
# later
student.grade = Grade.new(1)

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.

Console printing backwards

I'm trying to get the code to print the name of a class and then greetings on the same line. For example:
(DriveThru): Hi, welcome to Starbucks! What can I get started for you?
Here's my code:
module Order
def order_drink
"(#{self.class.name}): #{self.greeting}"
end
end
class Lobby
include Order
attr_reader :name
def initialize(name)
#name = name
end
def greeting
puts "Hi, welcome to Starbucks! How are you doing today #{self.name}?"
end
end
class DriveThru
include Order
attr_reader :name
def initialize(name)
#name = name
end
def greeting
puts "Hi, welcome to Starbucks! What can I get started for you #{self.name}?"
end
end
dt = DriveThru.new("Tom")
lb = Lobby.new("Jessica")
puts dt.order_drink
puts lb.order_drink
When I run the code, it prints the greeting first, line breaks, then prints the class name like this:
"Hi, welcome to Starbucks! What can I get started for you?"
(DriveThru):
What am I'm doing wrong?
Your greeting function is executing the puts statement. Due to the way Ruby (and most other programming languages) works, the order_drink method will evaluate the contents of the greeting method (calling a puts statement) first before returning its own value.
Dropping the puts at the beginning of each greeting function, for example:
class Lobby
include Order
attr_reader :name
def initialize(name)
#name = name
end
def greeting
"Hi, welcome to Starbucks! How are you doing today #{self.name}?"
end
end
This will cause your script to output the following:
(DriveThru): Hi, welcome to Starbucks! What can I get started for you Tom?
(Lobby): Hi, welcome to Starbucks! How are you doing today Jessica?
That said, it'd be preferable to add an attr_reader for the greeting attribute, and set its value in the initialize method (also known as the constructor), like so:
class Lobby
include Order
attr_reader :name, :greeting
def initialize(name)
#name = name
#greeting = "Hi, welcome to Starbucks! How are you doing today #{name}?"
end
end

Ruby Superclass creates a Stack error

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

Resources