Test input\output - ruby

I have code for the user input:
class Z
def self.input()
val = $stdin.gets.chomp
if val == "123"
p "Ok"
else
p "none"
end
end
end
I want to test different data:
describe "Z" do
it "should receive none"
Object.stub!(:gets){"das"}
Z.input
Object.should_receive(:p).with("none")
end
end
But i get an error:
Failure/Error: Object.should_receive(:p).with("none")
(<Object (class)>).p("none")
expected: 1 time
received: 0 times
How to test the output?
Thanks.

Try this:
describe Z do
it "should print into stdout" do
$stdin.stub(:gets).and_return("das")
$stdout.should_receive(:p).with("none")
Z.input
end
end

Related

Rubocop Lint: Useless assignment to variable

This code runs perfectly in the console but the linters keep failing with the error below..
This is the error:
refactored.rb:17:5: W: Lint/UselessAssignment: Useless assignment to variable - user_name. Did you mean user_age?
user_name = gets.chomp
refactored.rb:14:5: W: Lint/UselessAssignment: Useless assignment to variable - user_age. Did you mean user_name?
user_age = Integer(gets.chomp)
^^^^^^^^
This is the code:
require './school-library/student'
require './school-library/rental'
require './school-library/persons'
require './school-library/teacher'
require './school-library/book'
class Methods
def initialize
#person_array = []
end
def user_input
print 'Age: '
user_age = Integer(gets.chomp)
print 'Name: '
user_name = gets.chomp
end
def create_person
puts 'Do you want to create a student (1) or a teacher (2)? [Input the number]: '
person_option = Integer(gets.chomp)
case person_option
when 1
(user_age, user_name) = user_input
print 'Has parent permission? [Y/N]: '
user_permission = gets.chomp.to_s.upcase
case user_permission
when 'Y'
user_permission = true
when 'N'
user_permission = false
end
student = Student.new(user_age, user_name, parent_permission: user_permission)
#person_array.push({
output: "[Student] Name: #{student.name}, ID: #{student.id}, Age: #{student.age}",
object: student
})
puts 'Person created successfully!'
puts "\n"
when 2
(user_age, user_name) = user_input
print 'Specialization: '
user_specialization = gets.chomp
teacher = Teachers.new(user_age, user_name, user_specialization)
#person_array.push({
output: "[Teacher] Name: #{teacher.name}, ID: #{teacher.id}, Age: #{teacher.age}",
object: teacher
})
puts 'Person created successfully!'
puts "\n"
else
puts 'Person not created.'
end
end
def people_list
#person_array.each do |person|
puts person[:output]
end
end
def person_rent
#person_array.each_with_index do |person, index|
puts "#{index}) #{person[:output]}"
end
end
end
class BooksList
def initialize
#books = []
end
def create_book
print 'Title: '
book_title = gets.chomp
print 'Author: '
book_author = gets.chomp
puts 'Book created successfully!'
book = Book.new(book_title, book_author)
#books.push({
output: "Title: #{book.title}, Author: #{book.author}",
object: book
})
end
def book_list
#books.each do |book|
puts book[:output]
end
end
def rent_book
#books.each_with_index do |book, index|
puts "#{index}) #{book[:output]}"
end
end
end
RuboCop is trying to tell you that a useless variable exists in your code, but before fix that we need to talk about a bug happening right here:
(user_age, user_name) = user_input
In Ruby, a method returns the last line of code. Looking at the method user_input we can see that it returns only the user_name variable. The problem is that the (user_age, user_name) expects two values. The first is being assigned, but the second is given nil.
To fix that, update the method user_input to:
def user_input
print 'Age: '
user_age = Integer(gets.chomp)
print 'Name: '
user_name = gets.chomp
[user_age, user_name]
end
This will fix both the RuboCop offense and the bug.

Ruby Exceptions Initialize Error

I have to create a program where I have to ask the user for their first and last name on a single line. If the user puts only their first OR last name, it will be rejected through the exception. I keep getting an error at the end (below).
class MyNewException < Exception
attr_accessor :first, :last
def initialize (first, last)
#first = first
#last = last
end
end
print "Enter your first and last name:"
begin
first, last = gets.chomp.split
print "Hello," + first + " " + last + "!"
if last.size == 0
raise MyNewException, "Sorry, I didn't catch that! Try again:"
end
rescue MyNewException
puts "Sorry, I didn't catch that. Try again:"
retry
end
Keep getting an error:
testing.rb:15:in `+': no implicit conversion of nil into String (TypeError)
The raise() docs are faulty. You can do this:
puts "Enter your first and last name:"
name = gets.chomp
class MyNewException < Exception
def initialize(str)
super(str) #pass the value for the message property to the parent class
end
end
begin
raise MyNewException, "Sorry, I didn't quite catch that! Try again:"
rescue MyNewException => e
puts e.message
end
--output:--
Enter your first and last name:
Sarah Kim
Sorry, I didn't quite catch that! Try again:
Or:
puts "Enter your first and last name:"
name = gets.chomp
class MyNewException < Exception
attr_accessor :first, :last
def initialize(user_name, exception_message)
#first, #last = user_name.split
super exception_message
end
end
begin
raise MyNewException.new(name, "I didn't quite catch that! Try again:")
rescue MyNewException => e
puts e.message
puts e.first
puts e.last
end
--output:--
Enter your first and last name:
Sarah Kim
I didn't quite catch that! Try again:
Sarah
Kim
Here's how to write an infinite loop to get user input:
class Person
attr_accessor :first, :last
def initialize(first, last)
#first = first.capitalize
#last = last.capitalize
end
end
while true
puts "Enter your first and last name:"
first, last = gets.chomp.split
#Show what you got:
p first
p last
if first and last
#If no names were entered, both first and last will be nil.
#If one name was entered, first will evaluate to true and last will be nil.
#If two names were entered, first and last will evaluate to true.
#If two or more names were entered, first and last will evaluate to true.
user = Person.new first, last
break #jump to the line immediately after the infinite loop
end
puts "Sorry, you must enter both a first and a last name. Try again"
end
puts "Thanks #{user.first} #{user.last}!"
Create a loop that do your trial and error.
as for my answer I choose while loop
i = 0
while i < 1 do
if condition == true
# display your greetings then increment loop to end
i += 1
else
# display error message
end
end
So your code would be like this
class MyNewException < Exception
attr_accessor :first, :last, :valid
def initialize(first, last)
#first = first
#last = last
#valid = true
if first.empty? || last.empty? then
#valid = false
end
end
end
i = 0
while i < 1 do
print "Enter your first name: "
firstname = gets.chomp
print "Enter your last name: "
lastname = gets.chomp
name = MyNewException.new(firstname, lastname)
if name.valid then
puts "Greetings " << name.first << " " << name.last
i += 1
else
puts "I didn't quite catch that! Try again:"
end
end

ruby using if inside loop with user input

I trying to make loop through if statement if user input is invalid it keep telling to enter number only or break if true
I tried this is my code
class String
def numeric?
Float(self) != nil rescue false
end
end
cond = false
puts "Enter number "
line = gets.chomp.strip
while cond == false
if (line.numeric? )
puts "Ok nice "
cond = true
else
puts "Please enter number only "
end
end
but it keep looping if the condition is false just printing "Please enter number only "
i will be very happy for any suggestion
Thank you
The problem is that after telling the user to just enter a number you don't read another number, you just loop back around.
The easiest way to fix this is to move the prompt and input into the while loop, a bit like this:
class String
def numeric?
Float(self) != nil rescue false
end
end
cond = false
while cond == false
puts "Enter number "
line = gets.chomp.strip
if (line.numeric? )
puts "Ok nice "
cond = true
else
puts "Please enter number only "
end
end
try this:
while cond == false
if (line.numeric? )
puts "Ok nice "
cond = true
else
puts "Please enter number only "
line = gets.chomp.strip
end
end
Right after overriding String method, try this:
while true
print "Enter number "
line = gets.chomp.strip
if line.numeric?
puts "Ok nice"
break
else
puts "Please enter number only"
end
end

When creating an inventory, how do I keep people from adding a negative number?

I am creating a very simple "Repository" as my first real ruby script. I have the sections created where people can create an item and starting value, but I cannot seem to nail down how to keep people from incrementing (or decrementing) by 0 or negative numbers.
My code to add is as follows:
class Item
attr_accessor :name, :count
def initialize (name,initCount )
#name=name.downcase
#count=initCount
end
def add(amount)
#count += amount
end
def sub(amount)
#count -= amount
end
end
def prompt()
puts #items.inspect
puts " (A)dd item\n (R)emove item\n (L)ist items\n (I)ncrease item\n (D)ecrease items\n (Q)uit "
select = [(print '?: '), gets.rstrip][1]
if (select.upcase=="A") then
puts "Add Item\nItem name"
name=[(print 'Name? : '), gets.rstrip][1]
puts "Initial Count"
count= [(print 'Count? : '), gets.rstrip][1]
#items.push(Item.new(name,count.to_i)) unless #items.index(#items.find { |l| l.name == name })
end
Any help is appreciated.
Consider organizing your code like this. I may have made a few errors, but you'll get the idea.
PROMPT_TEXT =
" (A)dd item
(R)emove item
(L)ist items
(I)ncrease items
(D)ecrease items
(Q)uit ?: "
ILLEGAL_PROMPT_RESPONSE_MSG =
"You can't enter that! What were you thinking??"
NEGATIVE_NUMBER_MSG =
"If I've told you once, I've told you a thousand times: NO NEGATIVE NUMBERS!"
NOT_NUMBER_MSG =
"If that's a number, it must be Roman, and they aren't allowed."
TRY_AGAIN_MSG = "Try again...
.
def prompt()
loop do
puts #items.inspect # What's this?
puts PROMPT_TEXT
gets.rstrip.upcase case
when "A"
break if add_item
when "R"
...
when "L"
...
...
when "Q" then return
else
puts ILLEGAL_PROMPT_RESPONSE_MSG
end
puts TRY_AGAIN_MSG
end
end
.
def add_item
puts "Add Item\nItem name"
print 'Name? : '
name = gets.rstrip
puts "Initial Count"
print 'Count? : '
count = gets.rstrip
unless count =~ /\d+/
if count =~ /-\s*\d+/
puts NEGATIVE_NUMBER_MSG
else
puts NOT_NUMBER_MSG
end
return false
end
#items.push...
true
end
Aside: the statement
name=[(print 'Name? : '), gets.rstrip][1]
brings to mind a word that begins with "abomin" and ends with "ation". :-)
class Item
attr_accessor :name, :count
def initialize (name,initCount )
raise if initCount<0
#name=name.downcase
#count=initCount
end
def add(amount)
raise if amount<0
#count += amount
end
def sub(amount)
raise if amount<0 || amount>#count
#count -= amount
end
end

Ruby Script Error

In the gets portion at the lower half of the program, the terminal is not asking me for input but automatically taking input. I am unable to understand how this is happenening.
The Code is:
puts "Welcome to my automatic file opener"
puts "Version - 2.0"
if ARGV[0] && ARGV[1] #to ensure Arguements are given as input
old_data = File.open(ARGV[0]).readlines
new_data = File.open(ARGV[1]).readlines
class Differentiator
def old_stuff
puts "the old files are:-"
puts old_data
end
def new_stuff
puts "The new files are:-"
puts new_data
end
def updated_list
puts "The newly added files are:-"
newly_added = new_data - old_data
puts newly_added
end
def deleted_list
puts "The deleted files are:-"
deleted_data = old_data - new_data
puts deleted_data
end
def stable_list
puts "The unchanged/stable files are:-"
unchanged_data = new_data - newly_added
puts unchanged_data
end
end#end of class
while true
puts "Choose your option:"
puts "1.Old Files of System"
puts "2.New Files of System"
puts "3.Added Files of System"
puts "4.Deleted Files of System"
puts "5.Stable Lists"
puts "6.Exit"
print " Please Choose your Output:-"
**option_method=gets.chomp.to_i**
filecase1 = Differentiator.new
if option_method == 1
filecase1.old_stuff
end
if option_method == 2
filecase1.new_stuff
end
if option_method == 3
filecase1.updated_list
end
if option_method == 4
filecase1.deleted_list
end
if option_method == 5
filecase1.stable_list
end
if option_method == 6
break
exit
end
if option_method != (1..6)
puts "Sorry,Wrong Input"
end
end
else
puts "The Right Method of Usage is : ruby <scriptname>.rb old_file new_file"; exit;
end
Because you have to use $stdin.gets otherwise it will read the files given in ARGV.
It is written in the man page http://www.ruby-doc.org/core-2.0/Kernel.html in the first line talking about gets

Resources