Is there a "while...else" in Ruby? - ruby

I have a hash with cat names for keys and cat instances for values. Is there a way to make it so that when people type a response that isn't in a key in the cats hash for the terminal to reprint the puts "Which cat would you like to know about?" question or type: "Try again"? I guess I'm asking for sort of a "while... else".
puts "Which cat would you like to know about?"
puts cats.keys
response = gets.chomp
while cats.include?(response)
puts "The cat you chose is #{cats[response].age} old"
puts "The cat you chose is named #{cats[response].name}"
puts "The cat you chose is a #{cats[response].breed} cat"
puts "Is there another cat would you like to know about?"
response = gets.chomp
end

There isn't a "while...else", as far as I know. If you do not mind the loop continuing regardless of whether the response is a valid cat name or not, maybe this will work for you:
puts "Which cat would you like to know about?"
puts cats.keys
while true
response = gets.chomp
if response.empty?
break
elsif cats.include?(response)
puts "The cat you chose is #{cats[response].age} old"
puts "The cat you chose is named #{cats[response].name}"
puts "The cat you chose is a #{cats[response].breed} cat"
puts "Is there another cat would you like to know about?"
else
puts "There is no cat with that name. Try again."
end
end
This will repeatedly prompt the user for a cat name, until the user responds with an empty string, at which point it will break out of the loop.

You could rearrange your code with an additional question:
cats = {'a' => 1} #testdata
continue = true #set a flag
while continue
puts "Which cat would you like to know about?"
response = gets.chomp
while cats.include?(response)
puts cats[response]
puts "Is there another cat would you like to know about?"
response = gets.chomp
end
puts "Try another? (Y for yes)"
continue = gets.chomp =~ /[YyJj]/ #Test for Yes or yes, J for German J...
end

It has been a while since I have played with Ruby, but something like this comes to mind:
def main
print_header
while true
resp = get_response
if cats.include?(resp)
print_info(resp)
else
print_header
end
end
def get_response
puts cats.keys
response = gets.chomp
end
def print_header
puts "Which cat would you like to know about?"
end
def print_info response
puts "The cat you chose is #{cats[response].age} old"
puts "The cat you chose is named #{cats[response].name}"
puts "The cat you chose is a #{cats[response].breed} cat"
puts "Is there another cat would you like to know about?"
end
Please note that you will need a terminal point. If get_response returns "no", then quit.

continuous = false
loop do
unless continuous
puts "Which cat would you like to know about?", cats.keys
else
puts "Is there another cat would you like to know about?"
end
if cat = cats[gets.chomp]
puts "The cat you chose is #{cat.age} old"
puts "The cat you chose is named #{cat.name}"
puts "The cat you chose is a #{cat.breed} cat"
continuous = true
else
continuous = false
end
end

Related

My case statement is not working, but the logic looks correct to me

This program prints the first statement, and exits after I enter a number e.g. "5", without printing anything else. From the logic I put in the case statement, I would expect it to output "You're not an adult :(" for 5. Other values lower than 120 do not work as expected either.
What is wrong?
print "Enter you age "
age = gets.chomp
if age.to_i<120
case age.to_i
when age.to_i<18
puts "You're not an adult :("
puts "Sorry"
when age.to_i>18
puts "You are now an adult!"
puts "phew"
end
end
Try this. Notice I've dropped the age.to_i from the case statement:
print "Enter you age "
age = gets.chomp
if age.to_i<120
case
when age.to_i<18
puts "You're not an adult :("
puts "Sorry"
when age.to_i>18
puts "You are now an adult!"
puts "phew"
end
end
EDIT
A little explanation is in order.
When you write this:
case foo
when "bar"
...
That essentially means:
if "bar" === foo
...
So your code was sort of like this:
if age.to_i<18 === age.to_i
...
which doesn't make a lot of sense. If you just write case with nothing after it, then it works more like a regular if statement. E.g.
case
when foo === "bar"
...
means roughly
if foo === "bar"
...
which is what you want. I hope that helps!
Here's a cleaned up version:
print "Enter you age "
age = gets.chomp.to_i
case age
when 0..18
puts "You're not an adult :("
puts "Sorry"
when 18..120
puts "You are now an adult!"
puts "phew"
else
puts "I think you're lying!"
end
Folding all of this into a single case statement and using ranges makes what's happening a lot more clear.

how to save changes made in my .rb program in the terminal?

I'm really new to this but I’ve written a small program that will CRUD a movie to a list the only problem is it is not saving the changes made. how can I make this happen?
error = "movie not found"
movies = {
Mazerunner: 1
}
error = "movie not found"
puts "welcome to CrudMovies"
puts "enter a command"
puts "type add to add a movie to the list"
choice = gets.chomp.downcase
case choice
when "add"
puts "what movie would you like to add"
title = gets.chomp
if movies[title.to_sym].nil?
puts "what would you like the rating of #{rating} (1-4)to be?"
rating = gets.chomp
movies[title.to_sym] = rating.to_i
puts "#{title} was added with a rating of #{rating}"
else
puts "that movie already exists"
end
when "update"
puts "what movie would you like to update? (case sensitive)"
title = gets.chomp
if movies[title.to_sym].nil?
puts "#{error}"
else
puts "what is the movie rating would you like to update?"
movies[title.to symb] = rating.to_i
puts "#{title}'s rating has been updated to #{rating}"
end
when "display"
movies.each do |x, y|
puts "#{x} Rating:#{y}"
end
when "destroy"
puts "what movie would you like to erase?"
title = gets.chomp
if movies[title.to_sym].nil?
puts "#{error}"
else
movies.delete(title.to_sym)
puts "the movie no longer exists"
end
else
puts "command not recognized"
end
I'm going to assume that by "Save" you mean stored in the movies hash. The answer to that is that is it is in fact being stored. Only your script exits after you perform an operation, so you never get to see the updated movies.
To see the desired result you're going to want to wrap the majority of this in an infinite loop to prevent the script from naturally exiting.
Consider the following as an example:
store = []
while true
puts "Enter something:"
choice = gets.chomp
store.push choice
puts "Your choices so far are: #{store.inspect}"
end

How can I change a function argument into a variable?

Here is my code currently:
def name_grabber(name)
puts "What is your #{name} name?"
print "> "
$name = gets.chomp
print $name
end
name_grabber("first")
name_grabber("middle")
name_grabber("last")
puts "Nice to meet you, #{first} #{middle} #{last}"
puts
I want it so I can but first as a string into name_grabber and then first become a variable I can use later.
Using Ruby 2.0.0
I think this is what you want:
def name_grabber(name)
puts "What is your #{name} name?"
print "> "
gets.chomp
end
first = name_grabber("first")
middle = name_grabber("middle")
last = name_grabber("last")
puts "Nice to meet you, #{first} #{middle} #{last}"
puts

Two Parts, If I read in a file that's formatted like an array, can it be treated as such? And another about searching strings

I have two questions with this sample of code i'm about to drop in. The first deals with
person = gets.chomp
puts "Good choice! Here are #{person}'s tags!"
person = "#{person}.txt"
file = File.open(person)
while line = file.gets do
puts line
end
If the file that's opened is formatted exactly like an array (in this case its actually an array ruby has previously written to a txt file lets say, ["Funny", "Clever", "Tall", "Playboy"] ) Is there an easy way just make that an array again? Nothing I tried seemed to work.
The second deals with this
puts "Which tag would you like to vote on?"
tag = gets.chomp
if File.open(person).grep(/tag/) == true
puts "Found it!"
else
puts "Sorry Nope"
end
#f = File.new("#{person}")
#text = f.read
#if text =~ /tag/ then
#puts "Alright, I found that!"
#else
#puts "Can't find that sorry."
#exit
#end
This section just doesn't seem to be working. It never finds the string, also the commented out attempt didn't work either. I wasn't sure if the grep line actually returned a true or false value, but the commented out part avoids that and still doesn't return the string. I tried formatting the input with "" around it and every possible configuration ruby might be looking for but it always passes to the negative result.
and for the sake of completeness here is all the code.
puts "This is where you get to vote on a Tag!"
puts "Whose Tags would you like to alter?"
Dir.glob('*.txt').each do|f|
puts f[0..-5]
end
puts ".........."
person = gets.chomp
puts "Good choice! Here are #{person}'s tags!"
person = "#{person}.txt"
file = File.open(person)
while line = file.gets do
puts line
end
puts "Which tag would you like to vote on?"
tag = gets.chomp
if File.open(person).grep(tag) == true
puts "Found it!"
else
puts "Sorry Nope"
end
#f = File.new("#{person}")
#text = f.read
#if text =~ /tag/ then
#puts "Alright, I found that!"
#else
#puts "Can't find that sorry."
#exit
#end
Part 1 - Parse a string into an array
Use JSON.parse:
require 'json'
JSON.parse('["Funny", "Clever", "Tall", "Playboy"]')
# => ["Funny", "Clever", "Tall", "Playboy"]
Part 2 - Find a string in a file
As bjhaid recommended, use File.read and include?:
File.read(person).include?(tag)
This returns either true or false.
change:
if File.open(person).grep(tag) == true
puts "Found it!"
else
puts "Sorry Nope"
end
to
if File.read(person).include?(tag)
puts "Found it!"
else
puts "Sorry Nope"
end
File#open returns an IO object so you can't call grep on it like you would have done on an array, so I would suggest File.read which returns a String object that you can now call include? on

Question about "gets" in ruby [duplicate]

This question already has answers here:
Ruby: String Comparison Issues
(5 answers)
Closed 3 years ago.
I was wondering why when I'm trying to gets to different inputs that it ignores the second input that I had.
#!/usr/bin/env ruby
#-----Class Definitions----
class Animal
attr_accessor :type, :weight
end
class Dog < Animal
attr_accessor :name
def speak
puts "Woof!"
end
end
#-------------------------------
puts
puts "Hello World!"
puts
new_dog = Dog.new
print "What is the dog's new name? "
name = gets
puts
print "Would you like #{name} to speak? (y or n) "
speak_or_no = gets
while speak_or_no == 'y'
puts
puts new_dog.speak
puts
puts "Would you like #{name} to speak again? (y or n) "
speak_or_no = gets
end
puts
puts "OK..."
gets
As you can see it completely ignored my while statement.
This is a sample output.
Hello World!
What is the dog's new name? bob
Would you like bob
to speak? (y or n) y
OK...
The problem is you are getting a newline character on your input from the user. while they are entering "y" you are actually getting "y\n". You need to chomp the newline off using the "chomp" method on string to get it to work as you intend. something like:
speak_or_no = gets
speak_or_no.chomp!
while speak_or_no == "y"
#.....
end
once you use gets()...
print that string.. using p(str)
usually string will have \n at the end.. chomp! method should be used to remove it...

Resources