How to Add Values to a Hash in Ruby - ruby

I have done much research on this topic, but in every circumstance I attempt, the values appear to be replaced in the hash. After the person opts to enter a new ID, I would like the next person's name and age to be added to the hash. Could someone explain to me why the keys and values are being replaced?
class Person
def initialize(name, age)
if name != nil || age != nil
if #people != nil
#people[name.__id__] = age.__id__
else
#people = {name => age}
end
else
puts "Invalid credentials."
end
end
attr_reader :people
end
class MainInit
def initialize()
options = ["y", "yes", "n", "no"]
choice = "y"
while choice.downcase == "y" || choice.downcase == "yes"
p "Enter Name:"
inputname = gets.chomp
p inputname
p "Enter Age:"
inputage = gets.chomp
p inputage
person = Person.new(inputname, inputage)
p person.people
p "Enter another ID?"
choice = gets.chomp
until options.include? choice.downcase
p "Invalid Choice"
p "Enter another ID?"
choice = gets.chomp
end
end
end
end
MainInit.new

I think the reason the key-value pairs are being replaced is this:
The statement in your initialize method
if #people != nil
will always evaluate to false. initialize is called when you create a new object, so by default #people has not been defined or set yet, so each time you call
person = Person.new(inputname, inputage)
it creates a new Person rather than adding the new person to an exiting Hash (which is what I think you are trying to do).
It might work if you make people a class variable (##people), but it seems like you just want to create a Hash in your main program and then add the new entries in there.
So something like this
people = Hash.new # Or even just people = {}
Then when you have a new name / age entry to add
people[name] = age
I have not tried it, but I think your entire program should be reduced to something like this:
people = Hash.new
options = ["y", "yes", "n", "no"]
choice = "y"
while choice.downcase == "y" || choice.downcase == "yes"
p "Enter Name:"
inputname = gets.chomp
p inputname
p "Enter Age:"
inputage = gets.chomp
p inputage
#person = Person.new(inputname, inputage)
people[inputname] = inputage
person = people[inputname]
p person.people
p "Enter another ID?"
choice = gets.chomp
until options.include? choice.downcase
p "Invalid Choice"
p "Enter another ID?"
choice = gets.chomp
end

Let me both explain why you are having the problem you describe and also offer some suggestions for how you might change your code.
class Person
In class Person, you need to save your list of persons at the class level, which means the use of either a class instance variable (e.g., #people) or a class variable (e.g., ##people). I am with the majority of Rubiests in prefering the former. (The reasons are beyond the scope of this answer, but you will find a lot written on the subject by simply Googling, "Ruby 'class instance variables' versus 'class variables'". The inner quotes--the only ones you enter--help narrow the search.)
To define a class instance variable, #people, we just enter it as follows:
class Person
#people = {}
class << self
attr_accessor :people
end
def initialize(name, age)
self.class.people[name] = age
end
end
The # means it is an instance variable. As soon as Ruby reads class Person, it sets self to Person. It then reads #people = {} and makes that an instance variable of Person. By contrast, if you were to initialize #person within, say, an initialize method, self would at that time be an instance of Person, so #person would be a normal instance variable. (Aside: we could have both a class instance variable #person and an instance variable #person, and Ruby would treat them as differently as it would #night and #day.)
In order for objects to access #people we define an accessor. If we just entered attr_accessor :person, Ruby would create an accessor for a regular instance variable #person. Instead we enter class << self, which directs Ruby to associate what follows, until end is reached, with the class.
Each time a new instance of Person is created, for a given name and age,
self.class.people[name] = age
adds an element to the hash #person, since self.class is Person and people is the accessor.
Now look at the class MainInit
class MainInit
class MainInit
def initialize
loop do
name = nil
loop do
print 'Enter Name: '
name = gets.strip
break unless name.empty?
end
puts "name is #{name}"
age = nil
loop do
print 'Enter Age: '
age = gets.strip
case age
when /^\d+$/ && ('10'..'120')
break
else
puts 'age must be between 10 and 120'
end
end
puts "age is #{age}"
person = Person.new(name, age)
puts "people is now #{Person.people}"
loop do
print "Enter another ID? "
case gets.chomp.downcase
when 'n', 'no'
return
when 'y', 'yes'
break
else
puts 'Invalid choice'
end
end
end
end
end
loop do...end
You see that in several places I have used loop do...end with break to exit a loop. I'm a big fan of this construct, as compared to loop while... or or until..., in part because it avoids the need to enter a starting condition to get into the loop and then repeat the same condition withing the loop. I also just think it looks cleaner.
Any variables created within the loop cease to exist when you leave the loop, so if you want a variable's value (e.g., name and age), you must reference the variable outside of the beginning of the loops. That is why (and the only reason) I have name = nil and age = nil. It didn't have to be nil; I could have initialized them to anything.
Use of case statement
The loop for getting age uses this case statement:
case age
when /^\d+$/ && ('10'..'120')
...
end
This requires some explanation. The case statement uses String#===, rather than String#== to obtain truthy values. Therefore when /^\d+$/ is equivalent to:
/^\d+$/ === age
which is the same as
/^\d+$/ =~ age
The regex simply ensures that all characters of age are digits (e.g., "39).
Similarly,
('10'..'120') === age
is the same as
('10'..'120').cover?(age)
Odds and Ends
I used String#strip in place of String#chomp. Both remove ending newline characters, but strip also removes spaces the user may have entered at the beginning or end of the input string.
For strings, I mostly used single quotes, but double-quotes are needed for string interpolation. For example, I initially wrote puts 'name is #{name}'. That printed name is #{name}. After changing that to puts "name is #{name}", it correctly printed name is Debra.
Example
MainInit.new
Enter Name: Debra
name is Debra
Enter Age: 29
age is 29
people is now {"Debra"=>"29"}
Enter another ID? y
Enter Name: Billy-Bob
name is Billy-Bob
Enter Age: 58
age is 58
people is now {"Debra"=>"29", "Billy-Bob"=>"58"}
Enter another ID? u
Invalid choice
Enter another ID? n

Related

How to do user-inputted string templating in Ruby?

I know writing like
a=23
p "the value of a is #{a}"
it will print: the value of a is 23.
but now I am actually receiving this string as a parameter like
def evaluate string
a=23
puts string
end
calling method pass that string as a parameter
evaluate "the value of a is #{a}"
Is there any way to evaluate this string inside the method? puts string has to interpolate the value a=23.
Edit:
I have to read and execute the program from Excel.
At the first line,
Excel entry is,
"id=something" setvalue a
So now corresponding program will read the value from locator id=something and set it into the instance variable #a.
and user's next excel entry would be
"the value of a is 23" compare "the value of a is #{a}"
Now the program will read "the value of a is 23" and this "the value of a is #{a}" for comparison, but before it compares, it has to replace the value a. That's all I want. I hope now my question is very clear.
For ruby you can change how you "format" your strings in Excel, than you can use "classic" formatting
a = 23
s = 'the value of a is %s'
def evaluate(text, value)
puts text % value
end
You can use different formatting keys, for example %d for integers, %f for float numbers
You can use named arguments
dynamic_text = 'the value of the %<product_name>s is %<product_price>0.2f'
def evaluate(text, args)
puts text % args
end
name = "Product"
price = 78.99
evaluate dynamic_text, product_name: name, product_price: price
Without names, use order of the given values
dynamic_text = 'the value of the %s is %0.2f'
def evaluate(text, args)
puts text % args
end
name = "Product"
price = 78.99
evaluate dynamic_text, [name, price]
You can make a block and then evaluate the string:
def evaluate &block
a=23
block.call(a)
end
evaluate { |a| "the value of a is #{a}" } #=> "the value of a is 23"
It's a very odd thing you're attempting to do. When you have some sort of a pattern with placeholders, you do it like:
def evaluate(string)
a=23
format string, a: a
end
evaluate "the value of a is %{a}"
String interpolation with #{..} is not meant for the case you're describing as the value is evaluated at the time of constructing the string, not later. You could do some regexp matching and replace the #{..} with %{..} as a workaround.
There's a few ways:
"Code" Dynamic
lazy evaluation with lambdas:
def evaluate(str_template)
a = 23
str_template.call(a)
end
user_input = gets
my_lambda = lambda do |str|
user_input.size > 10 ? "dynamic 1 #{str}" : "dynamic 2 #{str}"
end
evaluate(my_lambda)
# => "dynamic 1/2 23"
This is "code dynamic", but not "input dynamic", i.e. you can't receive the string template from the user.
"Input" Dynamic 1
ERB templating:
require 'erb'
user_input_erb = gets
puts user_input_erb # "Hello <%= name %>"
name = gets # also user input, e.g. "World"
ERB.new(user_input_erb).result
# => "Hello World"
Note that in general, getting string templates from the user and evaluating them is a potential security vulnerability. If there's any possibility user input can be adversarial, you'll want to see if you can find a "guaranteed to be safe against all user input" string templating library.
"Input" Dynamic 2
user_input_template = gets
puts user_input_template # "Hello %s"
name = gets # also user input, e.g. "World"
user_input_template % name
# => "Hello World"
"Input" Dynamic 3
Really dangerous, but:
user_input_ruby_code = gets
puts user_input_ruby_code # '"Hello #{name}"'
name = gets # also user input, e.g. "World"
eval user_input_ruby_code # DANGER
# => "Hello World"

why is my input method for the hangman game failing to function properly?

I have this method where it gets an input from the user and it checks it against a while condition. if the user inputted anything that isnt a string or if the user inputted a character that was longer than 1 the method would prompt the user again for a valid input, basically adhering to the hangman rules. Heres the code
class Hangman
def initialize
dictionary = File.open('5desk.txt',"r")
line = dictionary.readlines
#word = line[rand(1..line.length)]
#length = #word.length
random = #word.length - rand(#word.length/2)
random.times do
#word[rand(#word.length)] = "_"
end
end
This method fails to function properly.
def get_input
puts #word
puts "Letter Please?"
#letter = gets.chomp
while !#letter.kind_of? String || #letter.length != 1
puts "Invalid input,try again!"
#letter = gets.chomp
end
end
end
Game = Hangman.new
Game.get_input
class Hangman
Stop right there! Why create a class considering that you would only create a single instance of it? There's no need for one. A few methods and one instance variable are sufficient.
Generate secret words randomly
I assume the file '5desk.txt' contains one secret words per line and you will be selecting one randomly. So begin by gulping the entire file into an array held by an instance variable (as opposed to reading the file line-by-line). I assume '5desk.txt1' contains the three words shown below.
#secret_words = File.readlines('5desk.txt', chomp: true)
#=> ["cat", "violin", "whoops"]
See the doc for the class method IO::readlines1,2. The option chomp: true removes the newline character from the end of each line.
This method closes the file after it has been read. (You used File::open. When doing so you need to close the file when you are finished with it: f = File.open(fname)...f.close.)
You need a method to randomly choose a secret_word.
def fetch_secret_word
#secret_words.sample
end
fetch_secret_word
#=> "violin"
See Array#sample. You could have instead used
#secret_words[rand(#secret_words.size)]
See Kernel#rand. The first and last words in #secret_words are #secret_words[0] and #secret_words[#secret_words.size-1]. Therefore, where you wrote
#word = line[rand(1..line.length)]
it should have been
#word = line[rand(0..line.length-1)]
which is the same as
#word = line[rand(line.length)]
Now let's create a method for playing the game, passing an argument that equals the maximum number of incorrect guesses the player has before losing.
def play_hangman(max_guesses)
First get a secret word:
secret_word = fetch_secret_word
Let us suppose that secret_word #=> "violin"
Initialize objects
Next, initialize the number of incorrect guesses and an image of the secret word:
incorrect_guesses = 0
secret_word_image = "-" * secret_word.size
#=> "------"
So we now have
def play_hangman(max_guesses)
secret_word = fetch_secret_word
incorrect_guesses = 0
secret_word_image = "-" * secret_word.size
Loop over guesses
Now we need to loop over the player's guesses. I suggest you use Kernel#loop, in conjuction with the keyword break for all your looping needs. (For now, forget about while and until, and never use for.) The first thing we will do in the loop is to obtain the guess of a letter from the player, which I'll do by calling a method:
loop do
guess = get_letter(secret_word_image)
...<to be completed>
end
def get_letter(secret_word_image)
loop do
puts secret_word_image
print "Gimme a letter: "
letter = gets.chomp.downcase
break letter if letter.match?(/[a-z]/)
puts "That's not a letter. Try again."
end
end
guess = secret_letter(secret_word_image)
#=> "b"
Here this method returns "b" (the guess) and displays:
------
Gimme a letter: &
That's not a letter. Try again.
------
Gimme a letter: 3
That's not a letter. Try again.
------
Gimme a letter: b
See if letter guessed is in secret word
Now we need to see which if any of the hidden letters equal letter. Again, let's make this a method3.
def hidden_letters(guess, secret_word, secret_word_image)
(0..secret_word.size-1).select do |i|
guess == secret_word[i] && secret_word_image[i] = '-'
end
end
Suppose guess #=> "i". Then:
idx = hidden_letters(guess, secret_word, secret_word_image)
#=> [1,4]
There are two "i"'s, at indices 1 and 4. Had there been no hidden letters "i" the method would have returned an empty array.
Before continuing let's look at our play_hangman is coming along.
def play_hangman(max_guesses)
secret_word = fetch_secret_word
incorrect_guesses = 0
secret_word_image = "-" * secret_word.size
loop do
unless secret_word_image.include?('-')
puts "You've won. The secret word is '#{secret_word}'!"
break
end
guess = get_letter(secret_word_image)
idx = hidden_letters(guess, secret_word, secret_word_image)
...<to be completed>
end
Process a guess
We now have to carry out one course of action if the array idx is empty and another if it is not.
case idx.size
when 0
puts "Sorry, no #{guess}'s"
incorrect_guesses += 1
if incorrect_guesses == max_guesses
puts "Oh, my, you've used up all your guesses, but"
puts "we'd like you take home a bar of soap"
break
else
puts idx.size == 1 ? "There is 1 #{guess}!" :
"There are #{idx} #{guess}'s!"
idx.each { |i| secret_word_image[i] = guess }
if secret_word_image == secret_word
puts "You've won!! The secret word is '#{secret_word}'!"
break
end
end
Complete method
So now let's look at the full method (which calls fetch_secret_word, get_letter and hidden_letters).
def play_hangman(max_guesses)
secret_word = fetch_secret_word
incorrect_guesses = 0
secret_word_image = "-" * secret_word.size
loop do
guess = get_letter(secret_word_image)
idx = hidden_letters(guess, secret_word, secret_word_image)
case idx.size
when 0
puts "Sorry, no #{guess}'s"
incorrect_guesses += 1
if incorrect_guesses == max_guesses
puts "Oh, my, you've used up all your guesses,\n" +
"but we'd like you take home a bar of soap"
return
end
else
puts idx.size == 1 ? "There is 1 #{guess}!" :
"There are #{idx.size} #{guess}'s!"
idx.each { |i| secret_word_image[i] = guess }
if secret_word_image == secret_word
puts "You've won!! The secret word is '#{secret_word}'!"
return
end
end
end
end
Play the game!
Here is a example play of the game.
play_hangman(4)
------
Gimme a letter: #
That's not a letter. Try again.
------
Gimme a letter: e
Sorry, no e's
------
Gimme a letter: o
There is 1 o!
--o---
Gimme a letter: i
There are 2 i's!
-io-i-
Gimme a letter: l
There is 1 l!
-ioli-
Gimme a letter: v
There is 1 v!
violi-
Gimme a letter: r
Sorry, no r's
violi-
Gimme a letter: s
Sorry, no s's
violi-
Gimme a letter: t
Sorry, no t's
Oh, my, you've used up all your guesses,
but we'd like you take home a bar of soap
1 The class File has no (class) method readlines. So how can we write File.readlines? It's because File is a subclass of IO (File.superclass #=> IO) and therefore inherits IO's methods. One commonly sees IO class methods invoked with File as the receiver.
2 Ruby's class methods are referenced mod::meth (e.g., Array::new), where mod is the name of a module (which may be a class) and meth is the method. Instance methods are referenced mod#meth (e.g., Array#join).
3 Some Rubyists prefer to write (0..secret_word.size-1) with three dots: (0...secret_word.size). I virtually never use three dots because I find it tends to create bugs. The one exception is when creating an infinite range that excludes the endpoint (e.g., 1.0...1.5).

DRY in Ruby - Is it okay to repeat a line of code?

I am newbie to programming and ruby. I am using a method to identify who somebody's secret santa is. The method takes String and Integer arguments (first name or id). I have different code for String and Integer arguments. This results in repeating the same line of code for different arguments (secret = PERSONS[person[:santa]-1]).
My questions are two-fold:
Is this kind of repetition against DRY principles? Is there another way to avoid the repetition?
See that I initialized local_variable secret outside the iterator and use the iterator to pass to that variable. Is this the most efficient way of doing this? Can I just return a value from the iterator without initializing a local variable?
My code is below. Also, I am enclosing a sample hash of data (PERSONS) that I am running the code on.
def who_is_secret_santa(first_name)
secret = nil
PERSONS.each do |person|
if first_name.is_a? String
if person[:first_name] == first_name
secret = PERSONS[person[:santa]-1]
end
elsif first_name.is_a? Integer
if person[:id] == first_name
secret = PERSONS[person[:santa]-1]
end
else
puts "Bad argument"
end
end
puts "#{first_name}'s Secret Santa " + (secret ? "is #{secret[:first_name]}" : "not found")
end
[{:id=>1,
:first_name=>"Luke",
:last_name=>"Skywalker",
:email=>"<luke#theforce.net>",
:santa=>4},
{:id=>2,
:first_name=>"Leia",
:last_name=>"Skywalker",
:email=>"<leia#therebellion.org>",
:santa=>7},
{:id=>3,
:first_name=>"Toula",
:last_name=>"Portokalos",
:email=>"<toula#manhunter.org>",
:santa=>5},
{:id=>4,
:first_name=>"Gus",
:last_name=>"Portokalos",
:email=>"<gus#weareallfruit.net>",
:santa=>2},
{:id=>5,
:first_name=>"Bruce",
:last_name=>"Wayne",
:email=>"<bruce#imbatman.com>",
:santa=>3},
{:id=>6,
:first_name=>"Virgil",
:last_name=>"Brigman",
:email=>"<virgil#rigworkersunion.org>",
:santa=>1},
{:id=>7,
:first_name=>"Lindsey",
:last_name=>"Brigman",
:email=>"<lindsey#iseealiens.net>",
:santa=>6}]
There is a way to avoid repetition in this case by first checking for a "bad argument" and then afterwards selecting the correct person from the array.
For your second question, you are probably looking for the select iterator instead of the each. It will return all of the elements in your array that make the condition in the block passed to it true.
Below is some code. p will represent the person whose first_name was passed to the method.
def who_is_secret_santa(first_name)
if ! ((first_name.is_a? String) || (first_name.is_a? Integer))
puts "Bad argument"
else
p = (PERSONS.select do |person| person[:first_name] == first_name || person[:id] == first_name end)[0]
puts "#{first_name}'s Secret Santa " + (p ? "is #{PERSONS[p[:santa]-1][:first_name]}" : "not found")
end
end

Ruby Character Creation for text RPG

First I just wanted to state I am very new to Ruby. I am a hug fan of Dnd and I wanted to create a text adventure game based off of Dnd rules. The issue I am having (I don't even know if it is possible) is that I am creating a character class and I want the variables assigned outside the class. The reason for this is I don't want the player to have to type:
character.new("Havatr", "elf", "tall and lean", "etc")
This is just an experiment before actually creating the file. This is what i have so far:
class Character
attr_reader :name, :race, :description
def initalize (name, race, description)
#name = name
#race = race
#description = description
end
end
def prompt
print "Enter Command >"
end
puts "What is your name?"
prompt; next_move = gets.chomp.downcase
puts "what is your race?"
prompt; next_move = gets.chomp.downcase
puts "What do you look like?"
prompt; next_move = gets.chomp.downcase
player_one = Character.new("#{a}","#{b}","#{c}")
print player_one
If there is a way to do this can I get assistance with it and if there is a better method then what I am trying please let me know. The idea behind this is to try and dump the class into a yaml file to create a character save.
When I run the code this is what it looks like:
What is your name?
Enter Command > Havatr
What is your race?
Enter Command > Elf
What do you look like?
Enter Command > I look like me
C://core_rules0.0.1/Characters.rb:27:in '': undefined local variable or method 'a' for main:Object (NameError)
There are two problems here. The first is that you misspelled initialize. The second is that instead of saving the values entered by the user in a, b, and c you save each in next_move. That's an easy fix:
puts "What is your name?"
prompt; name = gets.chomp.downcase
puts "What is your race?"
prompt; race = gets.chomp.downcase
puts "What do you look like?"
prompt; desc = gets.chomp.downcase
player_one = Character.new(name, race, desc)
print player_one
You'll notice that I did Character.new(name, race, desc) instead of Character.new("#{a}", "#{b}", "#{c}"). First, I used more descriptive names (one-character variable names are almost always a poor choice, except for well-known conventions like i to represent the iteration number in a loop). Second, I did name instead of "#{name}" because the latter doesn't actually do anything. #{...} is string interpolation in Ruby. It's a way to put values into a string, e.g. "Hello #{name}". But when you don't have anything else in the string, as in "#{name}", it doesn't do anything except convert a to a string—a task for which name.to_s is a better solution, and which is unnecessary anyway because we know name is already a string. "#{whatever}" is always unnecessary; whatever.to_s is sometimes necessary.
The other thing you'll notice is that print player_one prints something like:
#<Character:0x007fc23b88bf08>
...which maybe isn't what you expected. That's because Ruby doesn't know how to print your Character object in a human-readable way. You can tell it how by defining a to_s method. For example:
class Character
# ...
def to_s
"#{name} (#{race} - #{desc})"
end
end
For the inputs in your question, this would yield the following:
puts player_one
# => havatr (elf - i look like me)
(It's all lower-case because you called downcase on each input, which may or may not be the behavior you actually want.)
It looks like there is a simple bug here:
class Character
attr_reader :name, :race, :description
def initalize (name, race, description)
#name = name
#race = race
#description = description
end
end
def prompt
print "Enter Command >"
end
puts "What is your name?"
prompt; a = gets.chomp.downcase
puts "what is your race?"
prompt; b = gets.chomp.downcase
puts "What do you look like?"
prompt; c = gets.chomp.downcase
player_one = Character.new("#{a}","#{b}","#{c}")
print player_one
You were setting the results of the prompt to the variable next_move

Ruby - calling constructor without arguments & removal of new line characters

I have written down a sample program and I don't understand the following:
Why constructor without any arguments are not called in Ruby?
How do we access the class variable outside the class's definition?
Why does it always append newline characters at the end of the string? How do we strip it?
Code:
class Employee
attr_reader :empid
attr_writer :empid
attr_writer :name
def name
return #name.upcase
end
attr_accessor :salary
##employeeCount = 0
def initiaze()
##employeeCount += 1
puts ("Initialize called!")
end
def getCount
return ##employeeCount
end
end
anEmp = Employee.new
print ("Enter new employee name: ")
anEmp.name = gets()
print ("Enter #{anEmp.name}'s employee ID: ")
anEmp.empid = gets()
print ("Enter salary for #{anEmp.name}: ")
anEmp.salary = gets()
theEmpName = anEmp.name.split.join("\n")
theEmpID = anEmp.empid.split.join("\n")
theEmpSalary = anEmp.salary.split.join("\n")
anEmp = Employee.new()
anEmp = Employee.new()
theCount = anEmp.getCount
puts ("New employee #{theEmpName} with employee ID #{theEmpID} has been enrolled, welcome to hell! You have been paid as low as $ #{theEmpSalary}")
puts ("Total number of employees created = #{theCount}")
Output:
Enter new employee name: Lionel Messi
Enter LIONEL MESSI
's employee ID: 10
Enter salary for LIONEL MESSI
: 10000000
New employee LIONEL
MESSI with employee ID 10 has been enrolled, welcome to hell! You have been paid as low as $ 10000000
Total number of employees created = 0
The newlines are from the user input. When the user types something and terminates the input with a newline (enter key) the newline is seen as part of the input. You can strip it off with the String#strip() method:
empName = empName.strip
or use the in-place method:
empName.strip!
To retrieve the value of the class variable you need a static getter (note the self.):
def self.getCount
return ##employeeCount
end
Alternatively you can you the class_variable_get method.
For Question 1: Why constructor without any arguments are not called in Ruby?
You wrote def initiaze(). Correct would be def initialize():
def initialize()
##employeeCount += 1
puts ("Initialize called!")
end
as you seem to have noticed you misspelled initialize when
defining the method
you can't reference the class variable directly
outside the class, but you can make class or instance accessors for it, or use
Module#class_variable_get: Employee.class_variable_get(:##employeeCount)
gets returns the whole line the user inputs, including the terminating newline. Another answer recommended String#strip but this removes all trailing and leading whitespace. If you just want to remove the newline, use String#chomp, empName = empName.chomp! Be careful if you're tempted to apply chomp directly to gets as gets will return nil at end of file and you'll raise NoMethodError sending :chomp to nil
BTW, your camelCasedNames are not good ruby style. Constants should be all UPPER_CASE, except class and module names which should be CamelCased with leading cap, all other names should be lower_case_with_underscores_to_separate_words. Also, in ruby, one generally omits the empty parens on argumentless method calls and definitions.

Resources