I have to create a program where I have to ask the user for their first and last name on a single line. If the user puts only their first OR last name, it will be rejected through the exception. I keep getting an error at the end (below).
class MyNewException < Exception
attr_accessor :first, :last
def initialize (first, last)
#first = first
#last = last
end
end
print "Enter your first and last name:"
begin
first, last = gets.chomp.split
print "Hello," + first + " " + last + "!"
if last.size == 0
raise MyNewException, "Sorry, I didn't catch that! Try again:"
end
rescue MyNewException
puts "Sorry, I didn't catch that. Try again:"
retry
end
Keep getting an error:
testing.rb:15:in `+': no implicit conversion of nil into String (TypeError)
The raise() docs are faulty. You can do this:
puts "Enter your first and last name:"
name = gets.chomp
class MyNewException < Exception
def initialize(str)
super(str) #pass the value for the message property to the parent class
end
end
begin
raise MyNewException, "Sorry, I didn't quite catch that! Try again:"
rescue MyNewException => e
puts e.message
end
--output:--
Enter your first and last name:
Sarah Kim
Sorry, I didn't quite catch that! Try again:
Or:
puts "Enter your first and last name:"
name = gets.chomp
class MyNewException < Exception
attr_accessor :first, :last
def initialize(user_name, exception_message)
#first, #last = user_name.split
super exception_message
end
end
begin
raise MyNewException.new(name, "I didn't quite catch that! Try again:")
rescue MyNewException => e
puts e.message
puts e.first
puts e.last
end
--output:--
Enter your first and last name:
Sarah Kim
I didn't quite catch that! Try again:
Sarah
Kim
Here's how to write an infinite loop to get user input:
class Person
attr_accessor :first, :last
def initialize(first, last)
#first = first.capitalize
#last = last.capitalize
end
end
while true
puts "Enter your first and last name:"
first, last = gets.chomp.split
#Show what you got:
p first
p last
if first and last
#If no names were entered, both first and last will be nil.
#If one name was entered, first will evaluate to true and last will be nil.
#If two names were entered, first and last will evaluate to true.
#If two or more names were entered, first and last will evaluate to true.
user = Person.new first, last
break #jump to the line immediately after the infinite loop
end
puts "Sorry, you must enter both a first and a last name. Try again"
end
puts "Thanks #{user.first} #{user.last}!"
Create a loop that do your trial and error.
as for my answer I choose while loop
i = 0
while i < 1 do
if condition == true
# display your greetings then increment loop to end
i += 1
else
# display error message
end
end
So your code would be like this
class MyNewException < Exception
attr_accessor :first, :last, :valid
def initialize(first, last)
#first = first
#last = last
#valid = true
if first.empty? || last.empty? then
#valid = false
end
end
end
i = 0
while i < 1 do
print "Enter your first name: "
firstname = gets.chomp
print "Enter your last name: "
lastname = gets.chomp
name = MyNewException.new(firstname, lastname)
if name.valid then
puts "Greetings " << name.first << " " << name.last
i += 1
else
puts "I didn't quite catch that! Try again:"
end
end
Related
This code runs perfectly in the console but the linters keep failing with the error below..
This is the error:
refactored.rb:17:5: W: Lint/UselessAssignment: Useless assignment to variable - user_name. Did you mean user_age?
user_name = gets.chomp
refactored.rb:14:5: W: Lint/UselessAssignment: Useless assignment to variable - user_age. Did you mean user_name?
user_age = Integer(gets.chomp)
^^^^^^^^
This is the code:
require './school-library/student'
require './school-library/rental'
require './school-library/persons'
require './school-library/teacher'
require './school-library/book'
class Methods
def initialize
#person_array = []
end
def user_input
print 'Age: '
user_age = Integer(gets.chomp)
print 'Name: '
user_name = gets.chomp
end
def create_person
puts 'Do you want to create a student (1) or a teacher (2)? [Input the number]: '
person_option = Integer(gets.chomp)
case person_option
when 1
(user_age, user_name) = user_input
print 'Has parent permission? [Y/N]: '
user_permission = gets.chomp.to_s.upcase
case user_permission
when 'Y'
user_permission = true
when 'N'
user_permission = false
end
student = Student.new(user_age, user_name, parent_permission: user_permission)
#person_array.push({
output: "[Student] Name: #{student.name}, ID: #{student.id}, Age: #{student.age}",
object: student
})
puts 'Person created successfully!'
puts "\n"
when 2
(user_age, user_name) = user_input
print 'Specialization: '
user_specialization = gets.chomp
teacher = Teachers.new(user_age, user_name, user_specialization)
#person_array.push({
output: "[Teacher] Name: #{teacher.name}, ID: #{teacher.id}, Age: #{teacher.age}",
object: teacher
})
puts 'Person created successfully!'
puts "\n"
else
puts 'Person not created.'
end
end
def people_list
#person_array.each do |person|
puts person[:output]
end
end
def person_rent
#person_array.each_with_index do |person, index|
puts "#{index}) #{person[:output]}"
end
end
end
class BooksList
def initialize
#books = []
end
def create_book
print 'Title: '
book_title = gets.chomp
print 'Author: '
book_author = gets.chomp
puts 'Book created successfully!'
book = Book.new(book_title, book_author)
#books.push({
output: "Title: #{book.title}, Author: #{book.author}",
object: book
})
end
def book_list
#books.each do |book|
puts book[:output]
end
end
def rent_book
#books.each_with_index do |book, index|
puts "#{index}) #{book[:output]}"
end
end
end
RuboCop is trying to tell you that a useless variable exists in your code, but before fix that we need to talk about a bug happening right here:
(user_age, user_name) = user_input
In Ruby, a method returns the last line of code. Looking at the method user_input we can see that it returns only the user_name variable. The problem is that the (user_age, user_name) expects two values. The first is being assigned, but the second is given nil.
To fix that, update the method user_input to:
def user_input
print 'Age: '
user_age = Integer(gets.chomp)
print 'Name: '
user_name = gets.chomp
[user_age, user_name]
end
This will fix both the RuboCop offense and the bug.
Ok i seriously suck at passing method to methods whenever i want to return something from the method. Can you guys explain on how do i go about passing it.
Here's my hash
$choosen_gun = {}
$Weapon = {
:Bazoka => ["Bazoka",5],
:Machine_gun => ["Machine_gun",1000],
:Hand_gun => ["Hand_gun",24,2],
:Double_Hand_gun => ["Double_Hand_gun",24,4],
:Sniper => ["Sniper",12,1],
:Shot_gun => ["Shot_gun",8,2]
}
Here's my code for method Weapon
def Weapon
puts "Now it's time to select your weapon."
puts "Please choose a weapon that is good throughout the game."
puts "Whenever you are shortage of bullets, please reload it."
puts "Please avoid last minute of reloading of weapon."
puts "Now choose your weapon based on your own preferences."
print "\n"
puts "Type 1"
puts "Gun Name: Bazoka"
puts "Description: A powerful gun that is strong with only 5 bullets."
puts "Rating: ★ ★ ★ ★"
num = gets.chomp.to_i
case num
when 1
puts "Selection of Bazoka is chosen"
puts "Loaded 5 bullets only"
$choosen_gun[num] = $Weapon[:Bazoka]
end
return num
end
Upon calling the method. The user will choose his weapon and it will add it to the $choosen_gun hash with it's num, and it's return it's num what the user types
Here's my code for method ZombieRoom
def ZombieRoom(w)
zombie = {
:Construcied => [5],
:Invader => [5],
:Damned => [5],
:Steampunk => [5],
:Stoner => [5],
:Wasted => [5],
:Romero => [5]
}
puts "Welcome to the worst night mare of Zombie Room"
puts "You will be fighting with a random zombie"
while true
puts ".........."
puts "Selecting a random zombie"
puts "Selecting your prefered gun...."
case w
when 1
$choosen_gun[1]
puts "Your selected gun is #{$choosen_gun[1][0]}"
#values = zombie.values
#puts values[rand(values.size)]
#random_zombie = zombie.keys.sample(1)
#puts random_zombie[
random_zombie = zombie.to_a.sample(1).to_h
random_zombie.each do |key,value|
puts "Your random zombie is #{key}"
puts "With a health value of #{value[0]}"
puts "Time to take down that zombie now."
while true
puts "Type Shoot to knock it down or quit."
choice = gets.chomp
if $choosen_gun[1][1] >= 1
health = value[0] -= 1
$choosen_gun[1][1] -= 1
puts "#{key} health now is #{health}"
else
puts "Please reload your gun"
puts "Reloading......"
$choosen_gun[1][1] += 5
end
if health == 0
puts "You have defeated #{key}"
puts "Congrats!!!"
puts "We are happy for you"
puts "Lets begins to collect your prize"
CollectPrize()
else
puts "You did not defeat the #{key} yet"
end
end
end
end
end
end
Here's my code for method CollectPrize
def CollectPrize
puts "Congratulations on defeating"
puts "We would now like to give you some case prizes"
print "\n"
puts "Please choose only 1 prize for yourself"
print "\n"
puts "Type 1"
puts "$50,000"
print "\n"
puts "Type 2"
puts "$25,000"
print "\n"
puts "Type 3"
puts "$55,000"
hoho = gets.chomp.to_f
if hoho == 1
puts "hehe"
end
end
Here how i call my method
ZombieRoom(Weapon())
CollectPrize()
Now the problem is that whenever the CollectPrize method is called and i type my input to collect the prize example 1 then it print "$50,000". instead of the ending the problem, it went back to the ZombieRoom and continues to loop at the "Type Shoot to knock it down or quit." Can someone atleast tell me a proper way to solve this issue or also what other way to pass a method?
Your code is in a large while true loop. Since true is always true, it will never end, so after it calls CollectPrize() it just goes back to the while statement.
You could get out of it by inserting a break line after the CollectPrize() but there's another while true loop around this one.
I think you need to pay closer attention to how you want to exit the while loops.
puts "Time to take down that zombie now."
while true # <---------------- this is ALWAYS going to loop, without end
puts "Type Shoot to knock it down or quit."
choice = gets.chomp
if $choosen_gun[1][1] >= 1
health = value[0] -= 1
$choosen_gun[1][1] -= 1
puts "#{key} health now is #{health}"
else
puts "Please reload your gun"
puts "Reloading......"
$choosen_gun[1][1] += 5
end
if health == 0
puts "You have defeated #{key}"
puts "Congrats!!!"
puts "We are happy for you"
puts "Lets begins to collect your prize"
CollectPrize()
else
puts "You did not defeat the #{key} yet"
end
end
In ruby constants start with Capital letter.
Methods are always defined in lower case.
Try this in irb
irb(main):001:0> def Weapon
irb(main):002:1> end
=> :Weapon
irb(main):003:0> Weapon
NameError: uninitialized constant Weapon
To solve your problem name methods using ruby's naming conventions:
zombie_room, collect_prize etc.
Then this code will work:
zombie_room(weapon())
What you are doing there is not really passing method weapon to method zombie room.
What is really going on is that method weapon is executed, then it returns a value and result of that value is passed to method zombie_room.
I think that is what you wanted.
If you need to pass a method, check out documentation for proc and lambda or just use blocks.
Is there an alternative to iteration or a condition I can make that will allow me to interpolate the values of just one hash? I've inspected the results of my input and apparently the array that i'm saving my hashes into disappears when there is only one hash. I've also tested the results and they're of Nil class.
def print_with_index(students)
students.each_with_index do |student, index|
index_plus_one = index + 1
puts "#{index_plus_one}. #{students[:name]} (#{students[:cohort]} cohort)"
end
end
How do i solve my problem and also why do hashes behave this way?
Full code:
def print_header
puts "The students of Villains Academy"
puts "--------------"
end
def print_footer(names)
puts "Overall, we have #{names.count} great students"
end
def input_students
puts "Please enter the names and then the cohort of the students"
puts "To finish, just hit return twice"
#created an empty array
students = []
#getting the first name
name = gets.chomp
cohort = gets.chomp.to_sym
if cohort.empty?
cohort = :november
end
if cohort !~ /january|february|march|april|may|june|july|august|september|october|november|december/
puts "Please enter a valid month"
puts "Warning months are case sensitive. Please enter in lowercase characters."
cohort = gets.chomp.to_sym
end
while !name.empty? do
# add the student hash to the array called students
students << {name: name, cohort: cohort}
if students.count > 1
puts "Now we have #{students.count} students"
else students.count == 1
puts "Now we have #{students.count} student"
end
#getting another name from the user
name = gets.chomp
cohort = gets.chomp.to_sym
if cohort.empty?
cohort = :november
end
if cohort !~ /january|february|march|april|may|june|july|august|september|october|november|december/
puts "Please enter a valid month"
puts "Warning months are case sensitive. Please enter in lowercase characters."
cohort = gets.chomp.to_sym
end
end
bycohort = students.sort_by { |v| v[:cohort] }
filter = students.select! { |student| student[:cohort] == :november }
puts bycohort #This allows me to see all of my hashes before they are filtered
puts ""
bycohort
filter
end
def print_with_index(students)
students.each_with_index do |students, index|
index_plus_one = index + 1
puts "#{index_plus_one}. #{students[:name]} (#{students[:cohort]} cohort)"
end
end
### body ###
students = input_students
print_header
print_with_index(students)
print_footer(students)
this works for me though, i think with each_with_index enum, you have to pass in an array of hashes i.e. [{...}, {...}, {...}], not a single hash with multiple keys-values
def print_with_index(students)
students.each_with_index do |students, index|
index_plus_one = index + 1
puts "#{index_plus_one}. #{students[:name]} (#{students[:cohort]} cohort)"
end
end
print_with_index([{name:"b", cohort: "c"}])
# 1. b (c cohort)
You should use student instead of students as the block parameter. You can check if the student object is nil.
def print_with_index(students)
students.each_with_index do |student, index|
if !student.nil?
index_plus_one = index + 1
puts "#{index_plus_one}. #{student[:name]} (#{student[:cohort]} cohort)"
end
end
end
I am creating a very simple "Repository" as my first real ruby script. I have the sections created where people can create an item and starting value, but I cannot seem to nail down how to keep people from incrementing (or decrementing) by 0 or negative numbers.
My code to add is as follows:
class Item
attr_accessor :name, :count
def initialize (name,initCount )
#name=name.downcase
#count=initCount
end
def add(amount)
#count += amount
end
def sub(amount)
#count -= amount
end
end
def prompt()
puts #items.inspect
puts " (A)dd item\n (R)emove item\n (L)ist items\n (I)ncrease item\n (D)ecrease items\n (Q)uit "
select = [(print '?: '), gets.rstrip][1]
if (select.upcase=="A") then
puts "Add Item\nItem name"
name=[(print 'Name? : '), gets.rstrip][1]
puts "Initial Count"
count= [(print 'Count? : '), gets.rstrip][1]
#items.push(Item.new(name,count.to_i)) unless #items.index(#items.find { |l| l.name == name })
end
Any help is appreciated.
Consider organizing your code like this. I may have made a few errors, but you'll get the idea.
PROMPT_TEXT =
" (A)dd item
(R)emove item
(L)ist items
(I)ncrease items
(D)ecrease items
(Q)uit ?: "
ILLEGAL_PROMPT_RESPONSE_MSG =
"You can't enter that! What were you thinking??"
NEGATIVE_NUMBER_MSG =
"If I've told you once, I've told you a thousand times: NO NEGATIVE NUMBERS!"
NOT_NUMBER_MSG =
"If that's a number, it must be Roman, and they aren't allowed."
TRY_AGAIN_MSG = "Try again...
.
def prompt()
loop do
puts #items.inspect # What's this?
puts PROMPT_TEXT
gets.rstrip.upcase case
when "A"
break if add_item
when "R"
...
when "L"
...
...
when "Q" then return
else
puts ILLEGAL_PROMPT_RESPONSE_MSG
end
puts TRY_AGAIN_MSG
end
end
.
def add_item
puts "Add Item\nItem name"
print 'Name? : '
name = gets.rstrip
puts "Initial Count"
print 'Count? : '
count = gets.rstrip
unless count =~ /\d+/
if count =~ /-\s*\d+/
puts NEGATIVE_NUMBER_MSG
else
puts NOT_NUMBER_MSG
end
return false
end
#items.push...
true
end
Aside: the statement
name=[(print 'Name? : '), gets.rstrip][1]
brings to mind a word that begins with "abomin" and ends with "ation". :-)
class Item
attr_accessor :name, :count
def initialize (name,initCount )
raise if initCount<0
#name=name.downcase
#count=initCount
end
def add(amount)
raise if amount<0
#count += amount
end
def sub(amount)
raise if amount<0 || amount>#count
#count -= amount
end
end
Hi Im getting an core error which is really standard I suppose in Ruby but dont know what to make of it. I have a program that I have written. Its purpose is to register guests at a camping. You have a menu with 5 different options. 1. Checkin. When i do this I get a undefined method generateParkingLot' for #<Camping:0x10030a768> (NoMethodError)
When I choose Checkout I get a undefined local variable or methoddeparture' for Menu:Class (NameError).
So please i someone has a clue to my problem it would be great. I will here paste all my code. The code is separated in different files and I have used require for the different files. Here though I will paste all the code in one trace. Thankful for all help.
-Sebastien
require 'guest'
require 'parking_lot'
class Camping
attr_accessor :current_guests, :parking_lots, :all_guests, :staticGuests
def initialize(current_guests, parking_lots, all_guests, staticGuests)
#current_guests = Array.new()
# initiera husvagnsplatserna
#parking_lots = Array.new(32)
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
#staticGuests = Array[
Guest.new("Logan Howlett", "Tokyo", "07484822",1, #parking_lots[0]),
Guest.new("Scott Summers", "Chicago", "8908332", 2, #parking_lots[1]),
Guest.new("Hank Moody", "Boston", "908490590", 3, #parking_lots[2]),
Guest.new("Jean Grey", "Detroit", "48058221", 4, #parking_lots[3]),
Guest.new("Charles Xavier","Washington DC", "019204822",5, #parking_lots[4])
]
end
#all_guests = []
#staticGuests.each do |guest|
#current_guests[guest.plot.nr] = guest
#all_guests.push(guest)
end
end
def to_s
# creates an empty string
list = " "
# loop from 1 to 32
(1..32).each do |n|
if (!#current_guests[n-1].nil?)
list += #current_guests[n-1].to_s
else
# else adds the text "Vacant"
list += n.to_s + ": Vacant!\n"
end
return list
end
def generateParkingLot
randomNr = 1+rand(32)
# exists a guest at the (0-based) position?
if (!#current_guests[randomNr-1].nil?)
# if so generate a new figure
generateEmpty(array)
else
# returns the generated number
return randomNr
end
end
end
end
class Guest
attr_accessor :firstname, :lastname, :address, :phone, :departure
attr_reader :arrived, :plot
def initialize (firstName, lastName, address, phone, plot)
#firstName = firstName
#lastName = lastName
#address = address
#phone = phone
#arrived = arrived
#plot = plot
end
def to_s
"Personal information:
(#{#firstName}, #{#lastName}, #{#address}, #{#phone}, #{#arrived}, #{#departure}, #{#plot})"
end
end
require 'ruby_camping'
require 'camping_guests'
class Main
if __FILE__ == $0
$camping = Camping.new(#current_guests, #all_guests, #parking_lots,#staticGuests)
puts "\n"
puts "Welcome to Ruby Camping!"
while (true)
Menu.menu
end
end
end
require 'date'
require 'camping_guests'
require 'guest'
class Menu
def initialize(guests = [])
#camping = Camping.new(guests)
end
def self.menu
puts "---------------------------"
puts " Menu"
puts " 1. Checkin"
puts " 2. Checkout"
puts " 3. List current guests"
puts " 4. List all guests"
puts " 5. Exit\n"
puts ""
puts " What do you want to do?"
puts "---------------------------"
print ": "
action = get_input
do_action(action)
end
# fetches menu choice and returns chosen alternativ
def self.get_input
input = gets.chomp.to_i
while (input > 5 || input < 1) do
puts "Ooups, please try again."
input = gets.chomp.to_i
end
return input
end
def self.do_action(action)
case action
when 1:
check_in
when 2:
check_out
when 3:
puts $camping.current_guests
when 4:
puts $camping.all_guests
when 5:
puts "You are now leaving the camping, welcome back!"
exit
end
end
def self.check_in
puts "Welcome to the checkin"
puts "Please state your first name: "
firstName = gets.chomp
puts "Please state your last name:"
lastName = gets.chomp
puts "Write your address: "
address = gets.chomp
puts "and your phone number: "
phone = gets.chomp
puts "finally, your arrival date!"
arrived = gets.chomp
newPLot = $camping.generateParkingLot
newGuest = Guest.new(firstName, lastName, address, phone,arrived,$camping.parking_lots[newPLot-1])
$camping.current_guests[newPLot-1] = newGuest
#all_guests.push(newGuest)
puts "The registration was a success!! You have received the " + newPLot.to_s + "."
end
def self.check_out
puts "Welcome to checkout!"
puts $camping.all_guests
puts "State plot of the person to checkout!"
plot = gets.chomp.to_i
puts "Ange utcheckningsdatum: "
departureDate = gets.chomp.to_i
guest = $camping.current_guests[plot-1]
#departure = departure
guest.departure = departureDate
guestStayedDays = departureDate - guest.arrived
guest.plot.increase(guestStayedDays)
puts guest
$camping.current_guests[plot-1] = nil
end
end
class Parking_Lot
attr_accessor :nr
attr_reader :electricity_meter
def initialize (nr)
#nr = nr
#electricity_meter = 4000-rand(2000)
end
def increase_meter(days)
generatedUse = (10+rand(70))*days
puts "Increases the meter with " + generatedUse.to_s + " kWh."
#electricity_meter += generatedUse
end
def to_s
"Plot #{#nr+1} Electricity meter: #{#electricity_meter} kWh"
end
end
It looks (although I haven't tried this out) like some of your your 'end's are wrong.
The one which is causing your first error (generateParkingLot undefined) is that generateParkingLot is actually defined inside to_s, so you need an extra 'end' at the end of your to_s method.
As for the second error (departure not recognised), the folowing line in self.check_out is at fault:
#departure = departure
because there is no 'departure' variable. (Perhaps you meant DepartureDate?). I suspect there may be a few other issues with this code, but I'm afraid I don't really have time to check now.
One I noticed was that when you have
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
I think you might want to end that, either with an 'end' or curly brackets, e.g.
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
end
Although that would make your other blocks not match.. In general, just try and make sure your blocks are all defined properly (e.g. everything has a matching end).