Ruby - Making my code object orientated - ruby

I'm just starting out with OOP and am struggling to work out how to implement it. I can't work out how to create an instance of the class using the hash.new method. It's a basic program that takes input from a user and stores it in a hash. I was then planning on pushing the hash into an array to take advantage of the index. Below is the code
class Customer
def initialize(id, name, address, phone, email, bank_balance)
#id = id
#name = name
#address = address
#phone = phone
#email = email
#bank_balance = bank_balance
end
end
puts "Would you like to create an account?"
answer = gets.chomp
loop do
new_hash = {}
if answer.downcase.start_with?('y')
puts "Enter your name"
name = gets.chomp.downcase
new_hash['name'] = name
puts "Enter your address"
address = gets.chomp.downcase
new_hash['address'] = address
puts "Enter your ph number"
number = gets.chomp
number = number.split.join
new_hash['number'] = number
puts "Enter your email"
email = gets.chomp.downcase
new_hash['email'] = email
puts "Enter your bank balance"
bank_balance = gets.chomp
bank_balance = "$" + '%.2f' % bank_balance
new_hash['bank_balance'] = bank_balance
customer << new_hash
binding.pry
puts "Thankyou, details successfully Added"
break
else
break
end
end

you should remove everything inside initialize(...) and instead use
attr_accessor :name, :address, :phone, :email, :bank_balance) write it above your initialize statement
for more information on attr_accessor see this post What is attr_accessor in Ruby?
also follow it up by reading up on attr_reader and attr_writer
you can then assign values to those initialized variables in the rest of your code.
you will call your class by running Customer.new
you can get a little more snap out of your code by assigning your gets.chomp values to additional methods, then you can do something like
class Customer
attr_accessor :name, :address, :phone
def initialize
#name = ''
#address = ''
#phone = ''
end
def name
puts "Enter your name"
name = gets.chomp.downcase
end
def address
puts "Enter your address"
address = gets.chomp.downcase
end
def phone
puts 'enter your phone'
phone = gets.chomp
phone = phone.split.join
end
def all
name
address
phone
end
end
customer = Customer.new
customer.all

Related

Passing an object to a class initializer

I started learning Ruby today and immediately dove into a question of how to pass an object to another class as its initializer. How do I pass a Name and Address to the initializer of a Person?
Here is my code:
class Name
attr_accessor :first, :last
def initialize (first, last)
#first = first
#last = last
puts "created name"
end
def show ()
puts first, last
end
end
class Address
attr_accessor :street, :city, :state
def initialize (street, city, state)
#street = street
#city = city
#state = state
puts "Created addresss"
end
def show()
puts street, city, state
end
end
class Person
attr_accessor :name, :address
def initialize (name, address)
#name = name
#address = address
end
def show()
puts name
puts addr
puts "created person"
end
end
name = Name.new("Sam", "Spade")
name.show()
addr = Address.new("111 State St", "Albany", "NY")
addr.show()
person = Person.new (name, addr)
person.show()
The diagnostic I get is person.rb:48: syntax error, unexpected ')', expecting '='
...erson = Person.new (name, addr)
It might appear that the creation of the person object is missing a "p", but the code shows the "p" as being present.
I fixed a few bugs in your code.
class Name
attr_accessor :first, :last
def initialize (first, last)
#first = first
#last = last
puts "created name"
end
def show()
puts first, last
end
end
class Address
attr_accessor :street, :city, :state
def initialize (street, city, state)
#street = street
#city = city
#state = state
puts "Created addresss"
end
def show()
puts street, city, state
end
end
class Person
attr_accessor :name, :address
def initialize (name, address)
#name = name
#address = address
end
def show()
name.show
address.show
puts "created person"
end
end
name = Name.new("Sam", "Spade")
name.show()
addr = Address.new("111 State St", "Albany", "NY")
addr.show()
person = Person.new(name, addr)
person.show()
You had an extra space between new and the params Person.new (name, addr)
In the person class the variable is called address not addr
I think instead of putsing the objects in Person#show I'm guessing you wanted to call your show method which puts their attributes.
I think you got confused by the ellipses (...) in the syntax error. It was trying to simplify your code to the erroring part and it just so happened to cut off that p. The real issue is the space after new told the program to call the new method with no params passed in.

Using a variable across classes in Ruby

I have this class:
class Player
attr_accessor :card_pile, :name
def initialize
#name = name
#bust = false
#card_pile = []
end
def bust?
return #cards.inject(:+) > 21
end
end
I also have this as the beginning of another class
def playing_game
puts "How many players are playing? "
players_amount = gets.chomp.to_i
(0...players_amount).each do
puts ("What is the players name? ")
#name = gets.chomp
#players.push(#name)
end
#players.each do |each_player|
#name = Player.new
while true
while #name.card_pile.length < 2 do
new_card = Card.new
#name.card_pile.push(new_card.value)
end
puts(#name.card_pile)
print #name, "'s turn" "\n"
At the moment this will print out #<Player:0x007fc14984a4b0>'s turn instead of Rich's turn
Why is this happening? I thought I had made an instance variable in the Player class and then instantiated this class #name = Player.new and then could reference it from here on out??
This will help
def playing_game
puts 'How many players are playing?'
players_amount = gets.chomp.to_i
players_names = (0...players_amount).map do
puts ("What is the players name? ")
gets.chomp
end
players_names.each do |player_name|
player = Player.new(player_name)
while player.card_pile.length < 2 do
new_card = Card.new
player.card_pile.push(new_card.value)
end
puts player.card_pile
puts "#{player.name}'s turn"
end
end
UPD:
You don't need instance variables (like #name and #players inside single method).
In this code you iterate over players names
#players.each do |each_player|
=>
players_names.each do |player_name|
In context of
#name = Player.new
name is a Player instance
to create player with given name pass it to initializer:
player = Player.new(player_name)
then call name on Player instance, that you create earlier
puts "#{player.name}'s turn"

Dynamic variable from user input

I'm trying to get a user's input to create a new User object:
class User
attr_accessor :name
attr_accessor :age
attr_accessor :email
end
puts "Name:"
input = gets.chomp.to_s
name = "#{input} = User.new"
puts "Age:"
age = gets.chomp.to_s
puts "Email:"
email = gets.chomp.to_s
name.name = "#{input}"
name.age = "#{age}"
name.email = "#{email}"
puts "Name: #{input.name}, Age: #{input.age}, E-mail: #{input.email}"
How can I call the newly created object so that I can input new attributes? Do I need to change the name part of
name.name = "#{input}"
name.age = "#{age}"
name.email = "#{email}"
to the user's input?
In your case, input = gets.chomp.to_s is a String, and a string does not have any name, age and email methods you should be creating a new User object and then fill it with the information the user gives you, you're code is not so far from the answer but there are a lot's of little mistakes, here is the following working code:
class User
attr_accessor :name
attr_accessor :age
attr_accessor :email
end
user = User.new
puts "Name:"
user.name = gets.chomp.to_s
puts "Age:"
user.age = gets.chomp.to_s
puts "Email:"
user.email = gets.chomp.to_s
puts "Name: #{user.name}, Age: #{user.age}, E-mail: #{user.email}"
I hope it helps you.
By the way, what were you trying to achieve with this line: name = "#{input} = User.new" ? Because you're only creating a new string with the content "User.new" (as a string literal, it's not executed by Ruby in any way, you will never have a new object by surrounding its declaration with double (or single) quotes.

How can user input dynamically create objects?

I would like users to be able to dynamically create objects of the Incomes class below. That is, I would like to fire my program and let users enter as many incomes as they like, all stored as instances of the Incomes class.
def prompt
puts "> "
end
class Incomes
def initialize(aName, aAmount, aCOLA)
#name = aName
#amount = aAmount
#COLA = aCOLA
end
end
def addIncome
puts "What is the company name?"
prompt
aName = gets.chomp
puts "What is the monthly amount?"
aAmount = gets.chomp
puts "What is the cost of living adjustment?"
aCOLA = gets.chomp
end
#Now I want to be able to loop back through addIncome and create as many objects as the
#user wants. Perhaps there's a better way to store this type of data?
def prompt question
print "#{question} > "
gets
end
class Incomes
attr_reader :name, :amount, :COLA
##instances_of_Incomes = Array.new
def initialize(aName, aAmount, aCOLA)
#name = aName
#amount = aAmount
#COLA = aCOLA
#instances_of_Incomes = Array.new
end
def self.addIncome
name = prompt "What is the company name?"
amount = prompt "What is the monthly amount?"
_COLA = prompt "What is the cost of living adjustment?"
##instances_of_Incomes << Incomes.new(name, amount, _COLA)
end
def self.instances
##instances_of_Incomes
end
end
5.times do
Incomes.addIncome
end
puts Incomes.instances
Incomes.instances.each do |company|
puts company.name
end
I have refactored the code to show that you can use inputs to create the instances. They are unnamed classes, but stored in a class variable.
I also show that you can extract the name of each Incomes instance.
I have also edited your SE Code Review question, with the same code, so hopefully you can get some good reviews.

Creating Multiple Objects in Ruby and then Comparing Them

My goal is to be able to assign each tea their own ID, compare prices and weights between teas, and do it all within the command line. What's a smart way to do this? Here is my code so far:
class Tea
def initialize(name, price, shipping, weight)
#name = name
#price = price
#shipping = shipping
#weight = weight
get_tea_details
#total_price = total_price
end
def get_tea_details
puts "Enter name: "
#name = gets.chomp
puts "Enter price: "
#price = gets.chomp.to_f
puts "Enter shipping cost: "
#shipping = gets.chomp.to_f
puts "Enter weight: "
#weight = gets.chomp.to_i
end
def total_price
#total_price = #price + #shipping
end
def price_difference
price_difference = t1.total_price - t2.total_price
print "#{price_difference}"
end
end
puts "Do you want to compare teas?: "
answer = gets.chomp
if answer == "yes"
t1 = Tea.new(#name, #price, #shipping, #weight)
t1 = Tea.new(#name, #price, #shipping, #weight)
end
price_difference
I'm not exactly sure what you're asking, but my guess is you want to know how to write a function to compare your Tea objects. You can do something like this:
class Tea
attr_accessor :name, :price
def price_difference(other)
print (#price - other.price).abs
end
def compare(other)
same = true
if(#name != other.name)
puts "They have different names."
same = false
end
if(#price != other.price)
puts "They have different prices."
same = false
end
if same
puts "They are exactly the same!"
end
end
end
t1 = Tea.new
t2 = Tea.new
t1.compare t2
"They are exactly the same!"
I'd also recommend dropping the "tea_" prefix from your variables. It's unnecessary and adds a little readability.

Resources