One liner in Ruby for displaying a prompt, getting input, and assigning to a variable?
Check out highline:
require "highline/import"
input = ask "Input text: "
Ruby loops with user input
This is kind of a weird case. Because, first off, your instinct to loop is a good one. But you're in kind of an awkward situation because you haven't gotten to persisting data yet, which always makes these intro-level Ruby
examples kind of hard to learn. At least in my opinion.
But, this one actually might be kind of fun so I'm going to try and provide you with a solution that I hope will make sense. Disclosure: this will be very long and you may not understand what's going on. I will do my best to try and break it down line-by-line, but you might still be frustrated by some aspects of my answer. Because in reality, there's maybe something simpler out there that you can understand. But if you follow what I've written, play with it, and really try to understand it I think you will be in a really good spot to understand how Ruby conventions work moving forward. Be patient and be open.
Copy what I've added at the bottom into your text editor and save it. Run the file by running:ruby whatever_you_named_the_file.rb
Run through it a few times, enter in one employee then enter in the data for multiple employees. See how you can make it break. then look at the code change stuff around to see how it changes the output.
To address your point of "how would a loop automatically assign the input as employee_1?" The answer is, it won't. A loop has to be agnostic to the variables it assigns. Meaning all of the assignments will simply be to employee
, and each "instance" of a loop will only deal with one employee.
Anyway, here's the full code. Beneath this I'll try to break down each section and add comments throughout:
Here's the full code which you can put in an editor to mess around with:
$employees_array = []
def get_employee_data
puts "Name of your employee"
employee = gets.chomp!
puts "How much does #{employee} make per hour?"
employee_wage = gets.chomp!
puts "How many hours does #{employee} work per day?"
employee_hours = gets.chomp!
add_employee(employee, employee_wage, employee_hours)
puts "Do you have another employee you would like to enter?"
response = gets.chomp!
if response.downcase == "no"
display_employee_salaries
else
get_employee_data
end
end
def add_employee(employee, employee_wage, employee_hours)
employee_hash = {
name: employee,
wage: employee_wage.to_i,
hours: employee_hours.to_i,
}
$employees_array << employee_hash
end
def display_employee_salaries
$employees_array.each do |employee|
puts "Employee #{employee[:name]} makes $#{employee[:wage]} per hour and worked #{employee[:hours]}. That means their annual salary is: $#{ employee_salary(employee) } "
end
end
def employee_salary(employee)
employee[:wage] * employee[:hours] * 261 # 261 is the number of working days per year
end
get_employee_data
Now, to try and break that down:
$employees_array = [] # This is a global variable that will simulate a database for us so we can keep track of our employees.
def get_employee_data #the first half of this is largely similar to what you have. It will prompt the user for information.
puts "Name of your employee"
employee = gets.chomp!
puts "How much does #{employee} make per hour?"
employee_wage = gets.chomp!
puts "How many hours does #{employee} work per day?"
employee_hours = gets.chomp!
# Now we should hand this data off to another method, so that we can continue our loop and get more employees.
add_employee(employee, employee_wage, employee_hours) # this is a call to a method we define below. It passes all of the information gathered in the first loop so we can add another employee.
puts "Do you have another employee you would like to enter?"
response = gets.chomp!
# Now we decide if we want to loop again or return the output based on what the user says
if response.downcase == "no" #if the user says no, that's when we know to break the loop and calculate our salary data.
display_employee_salaries # this is another method that we've defined below, it is the final step to the loop.
else
get_employee_data # if a user says *anything* other than "no", we call this method, which will restart this loop. This might be confusing, that's because this is known as recursion--which can be a difficult concept to grasp. Be patient.
end
end
This is the first new method we need to define. What this does is creates a Hash of all of the data we gathered for one employee, it contains a "name", "wage", and "hours" based on what the user gave us in the previous method (above).
def add_employee(employee, employee_wage, employee_hours)
employee_hash = {
name: employee,
wage: employee_wage.to_i,
hours: employee_hours.to_i,
}
end
Remember the global variable at the top of the file? Now we just add this hash to the global Array.
$employees_array << employee_hash
The first time this runs the array will be empty, i.e.: []
The second time this runs the array will have an employee_hash inside: [employee_hash]
If another employee is entered, this line is executed again so the array will have [employee_hash, employee_hash]
This can happen for as many employees as you enter. So if you enter an employee 5 times the array will look like: [employee_hash, employee_hash, employee_hash, employee_hash, employee_hash]
You may be wondering "aren't those all the same? how does it know the difference?" The variable names are the same, the contents of the Hash are different. It doesn't know the difference. But it doesn't have to.
The second method we define is below. This gets called if the user answers "no" when asked "Do you have another employee you would like to enter?"
The responsibility of this method is to print out the employee salaries once all the employees have been entered.
To do this, we iterate (loop) through the global array of employees, and for each entry in that array, we do a puts command to print out our data. This is happening when we call ".each". It's saying, "For each item in this array, call it an "employee", and perform these actions". Once the array runs out of items, the loop ends and the program exits.
def display_employee_salaries
$employees_array.each do |employee|
puts "Employee #{employee[:name]} makes $#{employee[:wage]} per hour and worked #{employee[:hours]}. That means their annual salary is: $#{ employee_salary(employee) } "
end
end
Couple things to note: If you're unfamiliar with hash lookups- this is an example: employee[:name]
what this is doing, is it's looking for a "name" key in a hash called "employee". If there is a "name" key, then it will return to us the value. So if "employee" is a hash that looks like this:
{ name: "ActiveModel_Dirty", wage: "40", hours: "8" }
then employee[:name]
will return "ActiveModel_Dirty", employee[:wage]
will return "40", and so forth.
You may be wondering: "Hey, we called that hash employee_hash earlier, why are we suddenly referring to it as "employee"? Good question. after the .each do
below you'll see |employee|
. "employee" here can be whatever you want. it is how we refer to the current item we're iterating over only while inside this loop, it has no bearing on anything other than a reference point.
Lastly, you will notice a call to employee_salary towards the end of the puts command. This is calling another method that we define below.
The final method is used to do math——calculate an annual salary based on the information that the user gave us about an employee. It recieves an instance of an employee as an argument (that's what the (employee)) is.
It will calculate the wage, multiplied by the employee hours, multiplied by the working days in a year. Once it performs this calculation Ruby by default will return whatever it came up with. Which we then print to the console in the 'puts' statement above.
This method returns a number, that number is the value for the annual salary
def employee_salary(employee)
employee[:wage] * employee[:hours] * 261 # 261 is the number of working days per year
end
I really hope that helps you out and I hope it's not overwhelming. No one says you need to know how all of it works right now. Process as much as you can and then come back to it if you need to.
Ruby - If yes abc... end if no xyz
Here's a better way of expressing it:
puts "Do you like books?"
case (gets.chomp)
when 'yes'
puts "I do too"
when 'no'
puts "Movies better"
else
puts "I don't know what you mean."
end
The case
statement is great for breaking out multiple paths at the same time. gets
grabs input from the user. chomp
trims off the newline character that's automatically included.
Rails form: A field showing the value of one variable but saving it to another variable
You can supply a default value to an input field:
<%= f.email_field :new_email, value: @user.email, class: 'form-control' %>
Assign text from file to variable in Ruby without returning text
Start your irb as below :
irb --simple-prompt --noecho
--simple-prompt
is to get the IRB prompt as>>
--noecho
is to off the echo on IRB
Here is an example:
C:\>irb --simple-prompt
>> x = 2
=> 2
>> exit
C:\>irb --simple-prompt --noecho
>> x = 2
>>
How to use gets and gets.chomp in Ruby
gets
lets the user input a line and returns it as a value to your program. This value includes the trailing line break. If you then call chomp
on that value, this line break is cut off. So no, what you have there is incorrect, it should rather be:
gets
gets a line of text, including a line break at the end.- This is the user input
gets
returns that line of text as a string value.- Calling
chomp
on that value removes the line break
The fact that you see the line of text on the screen is only because you entered it there in the first place. gets
does not magically suppress output of things you entered.
Pass variables to Ruby script via command line
Something like this:
ARGV.each do|a|
puts "Argument: #{a}"
end
then
$ ./test.rb "test1 test2"
or
v1 = ARGV[0]
v2 = ARGV[1]
puts v1 #prints test1
puts v2 #prints test2
Related Topics
How to Install Ruby-Debug in Ruby 1.9.3/Rails 3.2.1
Sidekiq: Ensure All Jobs on the Queue Are Unique
Making Multiple Http Requests Asynchronously
Logging All Method Calls in a Rails App
Is There a Shorter Way to Require a File in the Same Directory in Ruby
Empty Attribute with Ruby Haml
Ruby on Rails: Debugging Rake Tasks
Can Bundler Show Me Which Gems in Gemfile Have Newer Versions (Eg. Dry-Run of Bundle Update)
How to Use Redis in a Multi-Threaded Rails Environment? (Puma/Sidekiq)
Hot Deploy on Heroku with No Downtime
Ruby: Extracting Words from String
Ruby: Proc.New { 'Waffles' } VS. Proc { 'Waffles' }
Install Bundler Gem Using Ansible
How to Set an Option as Selected Using Selenium Webdriver (Selenium 2.0) Client in Ruby
How to Install Nokogiri Ruby Gem with Mkmf.Log Saying Libiconv Not Found