Asking a user multiple questions using Ruby gets.chomp method - ruby

I'm very new to Ruby and practicing with user input. I have coded the following which allows the user to input names of students continuously until they hit return twice. After each input the program returns how many students are in the school, and when they are finished inputting for good, it prints out a list of the students and the cohort they are in.
At the moment, the cohort is hardcoded, and I want to modify this so that I can ask for both the name and the cohort, with the program continuing to ask for this info until the user hits return twice. Any help would really be appreciated - thanks :)
puts "Please enter the names of the students"
puts "To finish, just hit return twice"
students = []
name = gets.chomp
while !name.empty? do
students << {name: name, cohort: cohort}
puts "Now we have #{students.count} students"
name = gets.chomp
end
students
end
def print_header
puts "The students of this Academy".center(50)
puts "-----------".center(50)
end
def print(students)
students.each do |student, index|
puts "#{student[:name]} #{student[:cohort]} cohort"
end
end
end
def print_footer(names)
puts "Overall, we have #{names.count} great students".center(50)
end
students = input_students
print_header
print(students)
print_footer(students)

Instead of a while loop, I'd suggest to use loop do and break in case the name is empty (or also cohort):
loop do
puts "Please enter the names of the students"
name = gets.chomp
break if name.empty?
puts "Please enter the cohort"
cohort = gets.chomp
# break if cohort.empty?
students << {name: name, cohort: cohort}
end

Related

How to convert array into strings?

I have an output as such:
require_relative "array_sort"
arraystudents = []
puts "Type a student name:"
name = gets.chomp
arraystudents.push(name)
while name != ""
puts "Type another student name or press enter to finish:"
name = gets.chomp
arraystudents.push(name)
end
puts "Congratulations! Your Array has #{arraystudents.count} students: #{array_sort(arraystudents)}"
Every time I run it, I end up with an array output rather than just having the names under string form.
Is there a way where the output can be along the lines of: x, y and z? Rather than array, or just commas separating each name?
On another note, I seem to also have a blank [0] at the beginning of my array.
Here's on the array_sort.rb file.
def array_sort(students)
return students.sort.join(",")
end
Any help would be appreciated.
You're getting an extra blank entry at the end of arraystudents. arraystudents.sort makes it look at it's at the front.
The problem is because you check if name is empty, then you ask for a name and push it into arraystudents. Ask, push, then check. Instead you need to ask, check, then push.
arraystudents = []
loop do
puts "Type another student name or press enter to finish:"
name = gets.chomp
break if name == ''
arraystudents.push(name)
end
loop is an infinite loop. break lets you exit a loop.
Is there a way where the output can be along the lines of: x, y and z?
Yes. First handle the case when you have 0 or 1 students. This avoids results like and Zara.
When there's multiple students: Sort them. Remove the last student. Join the rest. Then concatenate them.
def display_students(students)
case students.size
when 0, 1
return students.first
else
sorted_students = students.sort
last = sorted_students.pop
return "#{sorted_students.join(', ')} and #{last}"
end
end
There may be more elegant ways, but it gets the job done.
You are inserting an element of the array also on the last iteration
i suggest doing something like this to avoid the last element of the array
arraystudents = []
puts "Type a student name:"
name = gets.chomp
arraystudents.push(name)
loop do
puts "Type another student name or press enter to finish:"
name = gets.chomp
break if name == ""
arraystudents.push(name)
end
puts "Congratulations! Your Array has #{arraystudents.count} students: #{arraystudents.sort.join(',')}"
The codes outputs
Type a student name:
1
Type another student name or press enter to finish:
2
Type another student name or press enter to finish:
3
Type another student name or press enter to finish:
Congratulations! Your Array has 3 students: 1,2,3
If you want to have the "and" you can do
arraystudents = []
puts "Type a student name:"
name = gets.chomp
arraystudents.push(name)
# puts arraystudents.join(',')
loop do
puts "Type another student name or press enter to finish:"
name = gets.chomp
break if name == ""
arraystudents.push(name)
# puts arraystudents.join(',')
end
arraystudents = arraystudents.sort
if (arraystudents.count == 1)
puts "Congratulations! Your Array has 1 students: #{arraystudents[0]}"
else
puts "Congratulations! Your Array has #{arraystudents.count} students: #{arraystudents[0..-2].join(',')} and #{arraystudents[-1]}"
end
and the output will be
Type a student name:
3
Type another student name or press enter to finish:
2
Type another student name or press enter to finish:
1
Type another student name or press enter to finish:
Congratulations! Your Array has 3 students: 1,2 and 3

validation on user input ruby

I created a gem that looks for a recipe with user input. I have almost 1000 recipes available to search for. How can I validate the user input when it does not match the names of my recipes?
as an example when the user type nabucodonosor or vocka the method load_recipe_by_ingridients return empty and I wish I could fix that. I'm using Ruby vanilla.. no rails
def start
puts "Hey there! you hungry? lets find some recipes ideas for you."
list_recipe_by_ingredients
show_summary
while #input != "exit"
if #input == "back"
list_recipe_by_ingredients
elsif valid_input?
puts Recipe.find_by_number(#input).summary
else
puts "Ops! not a valid number. try again."
end
ask_for_choices
end
end
def load_recipe_by_ingredients
puts "Search for recipes with the main ingredient, example: milk, pizza, eggs flour, ect."
#input = gets.strip.downcase
puts " "
Recipe.search_for_recipes(#input).each.with_index(1) do |recipe, index|
puts "#{index}. #{recipe.title}"
end
end
A pretty simple solution is to loop until a recipe is found, and once one or more recipes are found you break out of the loop and then render them:
def load_recipe_by_ingredients
recipes = []
loop do
puts 'Search for recipes with the main ingredient, example: milk, pizza, eggs flour, etc.'
input = gets.strip.downcase
puts
recipes = Recipe.search_for_recipes(input)
break if recipes.any?
puts 'No recipes found, please try again'
end
recipes.each.with_index(1) do |recipe, index|
puts "#{index}. #{recipe.title}"
end
end

Sentence rotate program not working ruby

I'm trying to write a program that takes a user's input (sentence), a word the user wants to rotate around, and outputs a rotated sentence around the word that has been chosen by user.
eg. Sentence: This is a book
Word to rotate around: book
Output: book This is a
I can't seem to exit this loop of entering data (the program keeps asking for input, not doing anything more.)
Please help. Here's my code:
class SentenceRotator
def get_sentence
puts "Please enter your sentence: "
sentence = gets.chomp
get_word
end
def get_word
puts "Please enter the word you want to rotate around: "
word = gets.chomp
if converts_sentence_to_array.include?(word)
rotate_sentence_around_word
else
puts "Your word isn't in the sentence. Please enter another word."
word = gets.chomp
end
rotate_sentence_around_word
end
def converts_sentence_to_array()
get_sentence.split(" ")
end
def rotate_sentence_around_word()
new_array = converts_sentence_to_array.each_with_index {|word,index| converts_sentence_to_array.rotate(index)}
new_array
end
end
new_app = SentenceRotator.new
new_app.rotate_sentence_around_word
new_app = SentenceRotator.new
new_app.rotate_sentence_around_word
So, calling methods: rotate_sentence_around_word => converts_sentence_to_array => get_sentence => get_word => converts_sentence_to_array => get_sentence => ...
Try something like this:
class SentenceRotator
def gets_user_data
puts "Please enter your sentence: "
#sentence = get_sentence.split(" ")
puts "Please enter the word you want to rotate around: "
#word = get_word_to_rotate_on
end
def get_sentence
gets.chomp
end
def get_word_to_rotate_on
word = gets.chomp
return word if #sentence.include?(word)
puts "Your word isn't in the sentence. Please enter another word."
get_word_to_rotate_on
end
def rotate_sentence_around_word()
gets_user_data
#sentence.rotate(#sentence.index(#word)).join(' ')
end
end
new_app = SentenceRotator.new
new_app.rotate_sentence_around_word
Here's the logic you want, split up into separate lines:
# input
sentence = 'This is a book'
word = 'book'
# processing
words = sentence.split
pos = words.index(word)
rotated = words.rotate(pos)
back_together = rotated.join(' ')
# output
p back_together
I'd advise you to separate out your processing code as much as possible. Then you can focus on the terminal input and output logic, which is what actually seems to be your issue.
I can't seem to exit this loop of entering data (the program keeps asking for input, not doing anything more.)
It looks like your foremost problem is to take the input from user properly and enter the rotation logic. You could make use of attr_reader to access the input across methods. I have made some changes to your class to accept the input in multiple steps:
class SentenceRotator
attr_reader :sentence, :rotate_on_word
def get_sentence
puts "Please enter your sentence: "
#sentence = gets.chomp
end
def get_word_to_rotate_on
puts "Please enter the word you want to rotate around: "
#rotate_on_word = gets.chomp
unless sentence.include?(rotate_on_word)
puts "Your word isn't in the sentence. Please enter another word."
get_word_to_rotate_on
end
end
def rotate
puts sentence
puts rotate_on_word
puts 'You have all the info. Add the logic to rotate.'
end
end
> new_app = SentenceRotator.new
> new_app.get_sentence
Please enter your sentence:
This is a very funny book
> new_app
=> #<SentenceRotator:0x00007fee44178c40 #sentence="This is a very funny book">
> new_app.get_word_to_rotate_on
Please enter the word you want to rotate around:
a
> new_app
=> #<SentenceRotator:0x00007fee44178c40 #sentence="This is a very funny book", #rotate_on_word="a">
> new_app.rotate
This is a very funny book
a
You have all the info. Add the logic to rotate.

Breaking a loop when a user types a certain input

So I'm trying to break a loop when a user type done and from there jump into another method called "survey" that asks a few leftover questions.
This is what I have a the moment:
def survey
puts "For how many years have you had these allergies?"
name = gets.chomp.to_i
puts "When was your last allergy reaction?"
reaction = gets.chomp.to_i
end
def allergies
puts "Please enter all your allergies. When you are finished, type 'done'."
allergy = gets.chomp.downcase!
while allergy != "done"
# Format the loop so that when the user types 'done'
# The loop breaks and we go to the 'survey' method
allergy = gets.chomp.downcase
survey
if allergy == "nuts"
puts "Beware! The food item contains peanuts!"
break
end
end
end
allergies
At the moment it just lets me type in one allergy and thenk skips right into the survey method. How can I change this so I can keep inputting allergies until I either type "nuts" or "done"?
def survey
puts "For how many years have you had these allergies?"
name = gets.chomp.to_i
puts "When was your last allergy reaction?"
reaction = gets.chomp.to_i
end
def allergies
puts "Please enter all your allergies. When you are finished, type 'done'."
allergy = gets.chomp.downcase!
while allergy != "done"
# Format the loop so that when the user types 'done'
# The loop breaks and we go to the 'survey' method
allergy = gets.chomp.downcase
if allergy == "nuts"
puts "Beware! The food item contains peanuts!"
break
elsif allergy == "done"
survey
end
end
end
allergies
Try an if-else statement
def allergies
puts "Please enter all your allergies. When you are finished, type 'done'."
allergy = gets.chomp.downcase!
while allergy != "done"
if allergy == "nuts"
puts "Beware! The food item contains peanuts!"
break
else
survey
end
allergy = gets.chomp.downcase
end
end

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

Resources