2

I'm trying to write a method that takes the user's input and checks it for validity. It's in a "case...when" statement. This part checks that the user has entered a Y or N only.

when 3
    input = gets.chomp.to_s.downcase
    unless input (=="y") || (=="n")
        puts "That is not a valid choice. Please enter Y or N."
        get_input(text, 3)
    end

The compiler doesn't like my boolean statement and I'm not sure why. It tells me "syntax error, unexpected [x]" and points to various parts of the statement. Pretty much tearing my hair out here... am I doing something obvious wrong?

5
  • 1
    Try this: unless ['y', 'n'].include?(input). Commented Sep 18, 2013 at 1:12
  • The syntax you want is unless (input=='y' or input=='n') Commented Sep 18, 2013 at 1:17
  • That's it. I knew it was something silly. Thanks Cary. Commented Sep 18, 2013 at 1:19
  • The solution that @depa suggested is more idiomatic ruby Commented Sep 18, 2013 at 1:19
  • 1
    One of the requirements for questions about code you wrote is you provide an example that is usable: "Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself." Saying "points to various parts of the statement" doesn't help at all. Commented Sep 18, 2013 at 1:28

4 Answers 4

4

Try this:

unless ['y', 'n'].include?(input)
Sign up to request clarification or add additional context in comments.

1 Comment

The best answer IMHO.
2

Depending on the language(s) you come from, you might find one of these different ways more appealing. You could write:

 unless input (=="y") || (=="n")

As:

if !input[/^[yn]$/]
    puts "That is not a valid choice. Please enter Y or N."
    get_input(text, 3)
end

Or:

unless input[/^[yn]$/]
  ...
end  

Or:

unless (input == 'y' || input == 'n')
  ...
end

Or:

case input
when 'y', 'n'
  ...
else
  puts "That is not a valid choice. Please enter Y or N."
  get_input(text, 3)
end

Comments

1

I find the unless first does not read well. Starting off with a negative would be fairly ok here but in more complicated conditionals it loses readability.

I personally prefer

$ if q !~ /[yn]/ # Does NOT match pattern
$   puts "That is not a valid choice. Please enter Y or N."
$   get_input(text, 3)    
$ end

for maximum easy readability by all.

Comments

0

Besides getting the condition right, there seems to be a recursion in your method. I suspect your method looks like this:

def get_input(text, option)
  # ...
  case option
  when 1
    # ...
  when 2
    # ...
  when 3
    unless condition
      puts "That is not a valid choice. Please enter Y or N."
      get_input(text, 3) # <- recursion!
    end
  end
  # ...
end

It would be better to use a loop here. Something like this:

def get_input(text, option)
  # ...
  case option
  when 3
    loop do
      valid = case gets.chomp
              when /^(y|yes)$/i
                puts "positive input"
                true
              when /^(n|no)$/i
                puts "negative input"
                true
              else
                puts "That is not a valid choice. Please enter Y or N."
                false
              end
      break if valid
    end
  end
end

The input is checked with another case statement. If the input is valid (i.e. y or n), true is returned and break exits the loop, otherwise false is returned, break is not called and the loops starts over again.

BTW, (y|yes) matches y and yes, (n|no) matches n and no, ^...$ ensures that there's nothing before or after, and the i makes it case insensitive.

So /^(n|no)$/i matches n, N, no, No, nO, and NO.

2 Comments

/^no?$/i would work as would /^y(es)?$/i. Using the non-capturing form ((?:es)?) is more proper, but wasted energy for this task.
Yes, but it would take me a second to understand what /^no?$/ is actually matching. Using alternation makes the regex very explicit and allows to add other values easily, e.g. /^(y|yes|ok)$/

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.