2

Here is my code:

loop do
  print "Input word: "
  word = gets.chomp
  if word.nil? or word.empty?
    puts "Nothing to input."
  else
    if word.index(":") != -1
      puts "Illegal character ':'"
    else
      break
    end
  end
end

Is there a more elegant way to check the input string?

4 Answers 4

9

Something like this?

loop do
  print "Input word: "
  word = gets.chomp

  if word.empty?
    puts "No input."
  elsif word.include?(":")
    puts "Illegal character ':'"
  else
    break
  end
end
Sign up to request clarification or add additional context in comments.

Comments

2

This separates the complex logic from the IO

def validation_message_for_word(word)
  case
  when (word.nil? or word.empty?) then "Nothing to input."
  when word.include?(":") then 'Illegal character ":".'
  else nil
  end
end

word = nil # To ensure word doesn't get thrown away after the loop
loop do
  print "Input word: "
  word = gets.chomp
  validation_message = validation_message_for_word(word)
  break if validation_message.nil?
  puts validation_message
end

Now, if you want to unit test it, you can give a variety of different strings to validation_message_for_word and test the return value.

If you needed internationalization, you could do

def validation_type_for_word(word)
  case
  when (word.nil? or word.empty?) then :no_input
  when word.include?(":") then :illegal_character
  else nil
  end
end

def validation_message(language, validation_type)
  {:en => {:no_input => "No input", :illegal_character => 'Illegal character ":"'},
   :lolcat => {:no_input => "Invizibl input", :illegal_character => 'Character ":" DO NOT LIEK'}}.fetch(language).fetch(validation_type)
end

word = nil # To ensure word doesn't get thrown away after the loop
loop do
  print "Input word: "
  word = gets.chomp
  validation_type = validation_type_for_word(word)
  break if validation_type.nil?
  puts validation_message(:lolcat, validation_type)
end

Comments

0

I personally prefer avoiding nested if/else:

loop do
    print "Input word: "
    word = gets.chomp
    if word.nil? or word.empty?
        puts "Nothing to input."
        #break, exit, nothing, or whatever ....
    end
    if word.index(":") != 0
        puts "Illegal character ':'"
    else
        break
    end
end

1 Comment

I understand your sentiment about nested if's, but in this case a simple elsif may be in order.
0

Depends what "elegant" means to you, but as a fan of refactoring conditional statements to easily readable extracted methods, I'd look at something like:

def has_valid_input(word)
  return true unless word.include?(":")
  puts "Illegal." 
  return false
end

def is_not_empty(word)
  return true unless word.empty?
  puts "empty"
  return false
end

loop do
  print "Input word: "
  word = gets.chomp
  break if is_not_empty(word) && has_valid_input(word)
end

6 Comments

This lacks proper MVC separation. Look at enterprise FizzBuzz for how it ought to be done! (I'm half joking, but I'm not sure this is the right way to do it)
I've had a go at separating logic from the output in my answer.
This is a ruby question - not an MVC framework question... So I answered in a Ruby way... not a Rails way.
Further more... bundling the two checks into one method using a case statement makes the code less readable (although I do prefer the idea of extracting the error messages - but at that point, I would probably be going back to the "problem" the whole code block is solving and determining whether any of this code is the right way to do it). Even further more, having a method for each of the validity checks makes the unit testing clearer, as each method is doing less.
@Pavling: You don't need a framework in order to do MVC separation.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.