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.
Related
I'm writing a short program that asks a user to enter a car model, maker, and year input and it passes that input through an algorithm. My question is, is there a way to label multiple printed outputs after it has been put through the formula to where it will number each output? Would I have to use a for each loop? I'm just trying to get a general idea of how I would accomplish this.
say for example the printed output would look like this.
class Car
attr_reader :make, :model, :year
def initialize
end
def set_make(make)
#make = make
end
def set_model(model)
#model = model
end
def set_year(year)
#year = year
end
def get_make
#make
end
def get_year
#year
end
def get_model
#model
end
end
array_of_cars = Array.new
print "How many cars do you want to create? "
num_cars = gets.to_i
for i in 1..num_cars
puts
print "Enter make for car #{i}: "
make = gets.chomp
print "Enter model for car #{i}: "
model = gets.chomp
print "Enter year of car #{i}: "
year = gets.to_i
c = Car.new
c.set_make(make)
c.set_model(model)
c.set_year(year)
array_of_cars << c
end
puts
puts "You have the following cars: "
puts
for car in array_of_cars
puts "#{car.get_year} #{car.get_make} #{car.get_model}"
end
puts
2014 Ford Expedition
2017 Toyota 86
2017 Aston Martin DB11
is there a way to add those numbers to the output?
Instead using a for loop you could try using each_with_index, which will allow you to get each element inside the array_of_cars and also the index for each element, in this case adding 1 to the current index will give you the value starting from 1:
array_of_cars.each_with_index do |car, index|
puts "#{index + 1}. #{car.get_year} #{car.get_make} #{car.get_model}"
end
Or you can use each and with_index passing the first element, in this case 1 as argument:
array_of_cars.each.with_index(1) do |car, index|
puts "#{index}. #{car.get_year} #{car.get_make} #{car.get_model}"
end
You don't need so many methods. Use attr_accessor to set getters and setters and utilize initialize better. Then using the basic idea from this answer by tadman, we can collect newly made objects into an array within the class itself. All together we can compress your class to:
class Car
attr_accessor :make, :model, :year
def self.all
#all ||= []
end
def initialize(make, model, year)
#make = make
#model = model
#year = year
Car.all << self
end
end
We can use times to run a piece of code n times.
puts "How many cars do you want to create? "
n = gets.to_i
n.times.with_index(1) { |_,i|
puts "Enter make for car #{i}"
make = gets.chomp
puts "Enter model for car #{i}: "
model = gets.chomp
puts "Enter year of car #{i}: "
year = gets.to_i
puts
Car.new(make, model, year)
}
Then as Sebastián Palma has already suggested, use each.with_index(1) to print your cars. The argument offsets the index by 1.
Car.all.each.with_index(1) { |c, i| puts "#{i}. #{c.year} #{c.make} #{c.make}" }
Sidenotes: 1. Avoid using for loops in Ruby 2. Use puts not print.
I would really appreciate it if I could get some help on some questions regarding an assignment that prints out the data typed in by a user(In this specific example, the year, model, and make of the car):
# DEFINE YOUR CAR CLASS HERE
# create empty array
array_of_cars = Array.new
# prompt for and get number of cars
print "How many cars do you want to create? "
num_cars = gets.to_i
# create that many cars
for i in 1..num_cars
# get the make, model, and year
puts
print "Enter make for car #{i}: "
make = gets.chomp
print "Enter model for car #{i}: "
model = gets.chomp
print "Enter year of car #{i}: "
year = gets.to_i
# create a new Car object
c = Car.new
# set the make, model, and year
# that we just read in
c.set_make(make)
c.set_model(model)
c.set_year(year)
# add the Car object to the array
array_of_cars << c
end
# print out the information for
# the Car objects in the array
puts
puts "You have the following cars: "
for car in array_of_cars
puts "#{car.get_year} #{car.get_make} #{car.get_model}"
end
I already have some part of the program, but struggle with the main portion of it, since I kind of know what to do but not how to implement it.
So for this part: # DEFINE YOUR CAR CLASS HERE
I got this:
class Car
def assign(m,n,y)
#instance variables
#make = m
#model = n
#year = y
end
#instance methods
def set_make
end
def set_model
end
def set_year
end
def get_make
end
def get_model
end
def get_year
end
First, did I do it right with the instance variables?
And then, the purpose of "set" is to save the value into the array right? and then "get" allows me to extract them later. I think I would understand the concept if someone could show me how to define one of them.
I know that this seems a bit vague, so I will try my best to clarify if some questions occur. Also sorry for the wall of text and thank you!
In the first place, in “idiomatic ruby” we call getters and setters for #variable as variable (getter) and variable= (setter.) The constructor is to be named initialize, not assign.
There is a helper to define both for the class, Module#attr_accessor that declares both getter and setter under the hood, so that your class definition might be as short as:
class Car
attr_accessor :make, :model, :year
def initialize(make, model, year)
#make = make
#model = model
#year = year
end
end
So far so good. The rest of your code would be:
array_of_cars = [] # use Array.new with parameter, [] otherwise
# prompt for and get number of cars
print "How many cars do you want to create? "
num_cars = gets.to_i
# create that many cars
(1..num_cars).each do |i| # in idiomatic ruby, never use for loops
# get the make, model, and year
puts "Enter make for car #{i}: "
make = gets.chomp
print "Enter model for car #{i}: "
model = gets.chomp
print "Enter year of car #{i}: "
year = gets.to_i
# create a new Car object
c = Car.new(make, model, year)
# add the Car object to the array
array_of_cars << c
end
# print out the information for
# the Car objects in the array
puts
puts "You have the following cars: "
array_of_cars.each do |car|
puts "#{car.year} #{car.make} #{car.model}"
end
BTW, instead of pre-creating an array, one might better use Enumerable#map:
# prompt for and get number of cars
print "How many cars do you want to create? "
num_cars = gets.to_i
# ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓ DECLARE IT IN-PLACE
array_of_cars = (1..num_cars).map do |i|
puts "Enter make for car #{i}: "
make = gets.chomp
print "Enter model for car #{i}: "
model = gets.chomp
print "Enter year of car #{i}: "
year = gets.to_i
# create a new Car object
Car.new(make, model, year)
end
That would produce an array needed out of the box.
Addendum: to define getter and setter manually:
class Car
attr_accessor :make, :model
def initialize(make, model, year)
#make = make
#model = model
#year = year
end
# manually declare getter for year:
def year
#year
end
# manually declare setter for year:
def year=(year)
#year = year
end
end
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"
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
I have created an array of objects containing information on the Oscars using a text file with all the category names, winners and nominees (winners appear in nominees list as well). I now want to be able to ask a user. Of which category would you like to know the winner? Once the question is asked it would return the answer. I can only get it to work on the last object of the array(best visual effects returns gravity). Can someone explain why this is happening?
class AwardCategory
attr_accessor :winner, :name, :nominees
def initialize(name)
#name = name
#nominees = []
end
end
class Nominee
attr_accessor :name
def initialize(name)
#name = name
end
end
file = File.open('oscar_noms.txt', 'r')
oscars = []
begin
while true do
award_category = AwardCategory.new(file.readline.downcase)
award_category.winner = file.readline.downcase
nominee = Nominee.new(file.readline.downcase)
award_category.nominees << nominee
next_nominee = Nominee.new(file.readline.downcase)
until next_nominee.name == "\n"
award_category.nominees << next_nominee
next_nominee = Nominee.new(file.readline.downcase)
end
oscars << award_category
end
rescue EOFError => e
puts 'rescued'
end
#puts oscars.inspect
#Read input here
puts "What category do you want to know the winner for?"
answer = gets
oscars.each
if answer.downcase == award_category.name
puts award_category.winner
else
puts "That is not a category"
end
That piece of code
puts "What category do you want to know the winner for?"
answer = gets
oscars.each
if answer.downcase == award_category.name
puts award_category.winner
else
puts "That is not a category"
end
Now with correct indentation
puts "What category do you want to know the winner for?"
answer = gets
oscars.each
if answer.downcase == award_category.name
puts award_category.winner
else
puts "That is not a category"
end
Note that the part below oscars.each is not indented, because each needs a do/end block which it will execute once for every element. What you probably want is this
puts "What category do you want to know the winner for?"
answer = gets
oscars.each do |award_category|
if answer.downcase == award_category.name
puts award_category.winner
else
puts "That is not a category"
end
end
Although I suggest you leave off the else, because you will get the message "That is not a category" for every answer that did not match. Also, you should use gets.chomp to remove the newline from the user input and do downcase outside of the each loop. As a last note, some of your variables are poorly named. For example, why should a list of award categories be named oscars? It should be award_categories instead.