0

I'm stuck trying to figure out how to make this method work.

I want to return true if the username is made up of lowercase characters, numbers, and underscores, and is between 4 and 16 characters in length, otherwise return false.

def validate_usr(username)
  if username == /A[a-z0-9_]{4,16}Z/
    return true
  else return false
  end
end

I don't know what I'm doing wrong.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Adil Ali
  • 11
  • 1
  • 2
  • 1
    Welcome to Stack Overflow. When asking, we need example input and your expected output. Please read "[mcve]". – the Tin Man Jan 29 '16 at 21:47
  • @theTinMan will do in the future, apologies – Adil Ali Jan 30 '16 at 07:51
  • Please don't only do it in the future, do it now, in this question. Edit it, add the appropriate information necessary to help you. As is, the question is one vote away from being closed because that information is missing. – the Tin Man Jan 31 '16 at 20:43

4 Answers4

5

I'd use something like:

def validate_usr(username)
  !!username[/\A\w{4,16}\z/]
end

validate_usr('foo')                # => false
validate_usr('foobar')             # => true
validate_usr('FooBar')             # => true
validate_usr('Foo Bar')            # => false
validate_usr('12345678901234567')  # => false

\w is the set [a-zA-Z0-9_], which includes uppercase too. If you don't want upper-case then use [a-z0-9_] for the set.

[/\A\w{4,16}\z/] is a String shortcut for applying a pattern to the string and returning the match. As the tests ran username[/\A\w{4,16}\z/] returned:

username[/\A\w{4,16}\z/]  # => nil, "foobar", "FooBar", nil, nil

!! converts "truthy"/"falsey" to true/false, so here are the actual results:

!!username[/\A\w{4,16}\z/]  # => false, true, true, false, false

The end result is the method returns the desired true/false results only with less code.

I used \z rather than \Z because you're testing usernames, presumably for correctness prior to creating an account. \z applies the test to the entire string, whereas \Z will ignore a trailing line-end. If your code were to somehow allow a user to create a name with a trailing line-end \Z would not give you an accurate validation result:

"foobar\n"[/\A\w{4,16}\Z/]  # => "foobar"
"foobar\n"[/\A\w{4,16}\z/]  # => nil
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
2

How about this?

def validate_usr(username)
  username =~ /\A[a-z0-9_]{4,16}\z/
end

Please read the following articles for the details of using regex.

Community
  • 1
  • 1
Junichi Ito
  • 2,438
  • 1
  • 23
  • 46
  • It worked! Thanks a lot! If you don't mind, could I ask a few questions about your answer? what does =~ do? why do you put forward slash before the A and Z? – Adil Ali Jan 29 '16 at 20:46
  • Might want to edit this to return a bool instead of a number. – Jeff K Jan 29 '16 at 20:48
  • @AdilAli gave a look at http://ruby-doc.org/core-2.1.1/Regexp.html the =~ matches a regular expression against a string. – Jeff K Jan 29 '16 at 20:51
  • @JeffK In such a case, it is very rare to distinguish "true" and "truthy value". I believe my code is more natural than your one. – Junichi Ito Jan 29 '16 at 21:28
  • 1
    @JunichiIto just trying to answer the question where he says he would like to return true if valid otherwise false. A lot of readers that glance at that might not realize the return value. – Jeff K Jan 29 '16 at 22:43
0

I think you're pretty close you'll want to use =~ for the regex comparison. It will return 0 if it is valid.

The match operator =~ can be used to match a string against a regular expression. If the pattern is found in the string, =~ returns its starting position; otherwise, it returns nil

def validate_usr(username)
  (username =~ /\A[a-z0-9_]{4,16}\Z/) == 0
end
Jeff K
  • 543
  • 2
  • 12
0

No regex:

def validate_usr(username)
  username.size.between?(4, 16) && username.count("^a-z0-9_").zero?
end
steenslag
  • 79,051
  • 16
  • 138
  • 171