Skip to content

MR05 Input Lab Solution

Dave Strus edited this page Feb 5, 2016 · 2 revisions

SOLUTION: Capturing User Input

Gathering the vital statistics of a single mutant.

In this solution, we'll learn about the following:

  • Using gets to capture user input
  • The difference between print and puts
  • String interpolation
  • The differences between single-quoted and double-quoted string literals
  • String#strip
  • String#chomp

The assignment

This was our assignment:

Prompt the user for the following pieces of data regarding a single mutant:

  • Real name (e.g. Aurelia)
  • Mutant name (e.g. Razorsnake)
  • Power (e.g. Razor-sharp scales)

Print something back to the screen to prove you got all of the information.

Let's break it down.

Prompting the user

Prompt the user

For a prompt, we'll print something to the screen. We can use our old friend puts:

puts 'Real name: '

Capturing the input

Then we need to capture the user's input, which we do with gets. We'll need to save it to a variable in order to use it later.

puts 'Real name: '
real_name = gets

Local variable names must start with a lowercase letter. It is conventional for variable names to be all lowercase, with underscores separating multiple words.

Displaying the result

Let's go ahead and add a line to prove we really did set the real_name to the user's input.

We can do it with string concatenation...

puts 'This mutant\'s real name is ' + real_name

...or string interpolation.

puts "This mutant's real name is #{real_name}."

String interpolation (with the #{...} syntax) only works in double-quoted string literals. The interpolated section doesn't have to be a single variable; it can be any Ruby expression.

Interpolation and a need to escape special characters like \n are the primary reasons to use double-quoted string literals. It is common to use single quotes wherever those features are not needed.

Read more about string literals in Ruby.

Initial Solution

Here's what we have so far:

roster.rb

#!/usr/bin/env ruby
puts 'Hello, mutant collector!'

puts 'Real name: '
real_name = gets
puts "This mutant's real name is #{real_name}."

Let's run it!

./roster.rb
Hello, mutant collector!
Real name:
Aurelia
This mutant's real name is Aurelia
.

There are a few things I'm not thrilled with, but the biggest problem is that the period at the end is on its own line. That's because gets includes the line-break entered by the user it the resulting string. So real_name contains "Aurelia\n".

We could use String#strip to remove whitespace from the beginning and end of the string. There's also rstrip, which removes whitespace only from the end.

String#chomp, without any arguments is probably the best fit for what we're doing here. It will remove a trailing line break (either "\n" or "\r\n") from the end of the string.

We could call chomp when we print the result to the screen...

puts "This mutant's real name is #{real_name.chomp}."

...but it probably makes more sense to chain chomp on the end of gets when we first assign the string.

real_name = gets.chomp

Let's run it again.

$ ./roster.rb
Hello, mutant collector!
Real name:
Aurelia
This mutant's real name is Aurelia.

That's much better, but there is one other thing bothering me: I think it would look nicer if the user entered the name on the same line as the prompt, like this:

Real name: Aurelia

That's an easy enough fix. We can use print in place of puts. The former prints the string as-is, while the latter adds a newline to the end if one is not already there.

Let's change our prompt...

print 'Real name: '

...and run it again.

./roster.rb
Hello, mutant collector!
Real name: Aurelia
This mutant's real name is Aurelia.

Beautiful!

Now it's easy enough to build it out with the other two pieces of data.

SOLUTION

#!/usr/bin/env ruby
puts 'Hello, mutant collector!'

print 'Real name: '
real_name = gets.chomp
print 'Mutant name: '
mutant_name = gets.chomp
print 'Power: '
power = gets.chomp
puts "#{mutant_name} (also known as #{real_name}) has an incredible power: #{power}."

Seems to do the trick:

$ ./roster.rb
Hello, mutant collector!
Real name: Aurelia
Mutant name: Razorsnake
Power: Razor-sharp scales
Razorsnake (also known as Aurelia) has an incredible power: Razor-sharp scales.

That's worth a commit! Before committing, review the changes you've made since the previous commit.

$ git diff
diff --git a/roster.rb b/roster.rb
index d4f7211..a8a1fa1 100755
--- a/roster.rb
+++ b/roster.rb
@@ -1,2 +1,10 @@
 #!/usr/bin/env ruby
 puts 'Hello, mutant collector!'
+
+print 'Real name: '
+real_name = gets.chomp
+print 'Mutant name: '
+mutant_name = gets.chomp
+print 'Power: '
+power = gets.chomp
+puts "#{mutant_name} (also known as #{real_name}) has an incredible power: #{power}."

All we did was add new lines to our script. We didn't change any existing lines. Looks ready to commit.

$ git add .
$ git commit -m "Prompt for a mutant's real name, mutant name, and power."

We know Ruby is supposed to be object-oriented, but this script doesn't seem particularly object-oriented. What exactly is going on here anyway? Let's dig in and find out.