Reputation: 151
My method handles the program loop for true/false. The code takes a number of integers, then checks:
The code is:
def self.number_validator(*numbers)
numbers.each do |number|
unless number.is_a?(Integer)
puts "#{number} is not an integer"
return false
end
unless number > 0 && number < 100
puts "#{number} is out of range"
return false
end
end
return true
end
My understanding is that returning false
will exit the whole method. I'm concerned and want to make sure that it does not break only the loop and return to the return true
section. I want to make sure that the true value doesn't get triggered by the false value closing the loop and moving back to the overall method (rather than actually just reporting false and stopping the method).
Upvotes: 0
Views: 57
Reputation: 28305
I'm concerned (and want to make sure) that [it works].
It does work (almost). With the slight mistake that you've written < 100
instead of <= 100
.
return
exits the method immediately. The keyword break
, on the other hand, would only exit the loop.
But don't just take my word for it. (And asking someone on StackOverflow whether or not your code works isn't an efficient way to go about testing it!) Let's write a few tests for your code:
require 'rspec'
RSpec.describe 'number_validator' do
subject { number_validator(*input) }
context 'integers only (valid input)' do
let(:input) { [1, 5, 80, 100] }
it { is_expected.to eq true }
end
context 'non positive integer' do
let(:input) { [1, 5, 0] }
it { is_expected.to eq false }
end
context 'integer greater than 100' do
let(:input) { [1, 5, 101] }
it { is_expected.to eq false }
end
context 'non integer' do
let(:input) { [1, 5, 'BAD'] }
it { is_expected.to eq false }
end
end
You could write more edge cases too if you like, e.g. what if there is no input given (number_validator()
), or a negative number (number_validator(-1)
), or a non-integer number (number_validator(3.5)
), ...
Now that we have some tests, let's try rewriting that method slightly to something more elegant. We can be confident that it still works, because the tests should still pass!
Rather than using Array#each
with multiple return
statements, we can instead use Enumerable#all?
to do the same thing in much less code (if you're willing to drop the puts
statements):
def number_validator(*numbers)
numbers.all? { |number| number.is_a?(Integer) && number > 0 && number <= 100 }
end
We can then simplify this even further, using Comparable#between?
:
def number_validator(*numbers)
numbers.all? { |number| number.is_a?(Integer) && number.between?(1, 100) }
end
Upvotes: 4