Ranges use cover? for case equality. So it is comparing '3' >= '0' && '3' < '10' which results in false because '3' < '10' #=> false. Strings are compared based on character values.
For a better understanding you might want to see a string as an array of characters:
['3'] <=> ['1', '0'] #=> 1 (first operand is larger than the second)
To solve the issue convert your case input to an integer and use integer ranges:
case 3 # or variable.to_i
when 0...10
puts 'number is valid'
else
puts 'number is invalid'
end
This works because integers are not compared based on character code, but on actual value. 3 >= 0 && 3 < 10 results in true.
Alternatively you could explicitly tell when to use the member? (or include?) method, by not passing a range, but a method instead.
case '3'
when ('0'...'10').method(:member?)
puts 'number is valid'
else
puts 'number is invalid'
end