/ / O que há de errado com este Regex em Ruby on Rails? - ruby-on-rails, regex

O que há de errado com este Regex em Ruby on Rails? - ruby-on-rails, regex

Eu escrevi um regex para ajudar a validar um String para nomes de caracteres de jogos. De alguma forma, ele está transmitindo seqüências aparentemente inválidas e não passando strings aparentemente válidas.

Requisitos:

  • Começa com letra maiúscula
  • Tem qualquer número de caracteres alfanuméricos depois disso (isso inclui espaços)

Este é o código de trilhos que faz a validação no Modelo de Personagem:

validates :name, format: { with: %r{[A-Z][a-zA-Z0-9s]*} }

Aqui está o teste de unidade que eu estou usando

test "character name should be properly formatted and does not contain any special characters" do
character = get_valid_character
assert character.valid?

character.name = "aBcd"
assert character.invalid?, "#{character.name} should be invalid"

character.name = "Number 1"
assert character.valid?, "#{character.name} should be valid"

character.name = "McDonalds"
assert character.valid?, "#{character.name} should be valid"

character.name = "Abcd."
assert character.invalid?, "#{character.name} should be invalid"

character.name = "Abcd%"
assert character.invalid?, "#{character.name} should be invalid"
end

Os problemas: O regex passa "aBcd", "Abcd." E "Abcd%" quando não deveria. Agora, eu sei que isso funciona porque eu testei isso em Python e funciona exatamente como você esperaria.

O que da?

Obrigado pela ajuda!

Respostas:

6 para resposta № 1

Expressões regulares procuram por correspondências em qualquer lugar da string dada, a menos que seja dito o contrário.

Então a string de teste "aBcd" é inválido, mas contém uma substring válida: "Bcd". Mesmo com "Abcd%", onde a substring válida é "Abcd".

Se você quiser corresponder a string inteira, use isso como seu regex:

# A matches string beginning, z matches string end
%r{A[A-Z][a-zA-Z0-9s]*z}

PS: Algumas pessoas vão dizer para combinar o começo de uma string com ^ e o fim com $. Em Ruby, esses símbolos correspondem ao começo e ao fim de um linhanão uma string. assim "ABCDn%" ainda corresponderia se você usou ^ e $, mas não vai combinar se você usar A e z. Veja o Guia de segurança do Rails para mais sobre isso.


0 para resposta № 2

Se você quer apenas combinar a letra maiúscula no começo da string, você precisa colocar o marcador "início da linha" ^ então ficaria assim:

validates :name, format: { with: %r{^[A-Z][a-zA-Z0-9s]*} }

Confira Rubular para brincar com o seu regex