É um tanto comum em uma aplicação Rails querer incluir um
slug de URL customizado como parte de um modelo. Por exemplo, se você tem um User
modelo e deseja que
esses usuários tenham uma página de perfil acessível em /users/john-smith
,
você deseja armazenar esse "john-smith"
valor no modelo e garantir que
ele seja único. Eu chamo esse campo de “lesma”.
Digamos que você queira permitir que os usuários editem seus próprios slug e decidam o que será inserido no
URL de seu perfil. Neste caso, você deseja adicionar algumas restrições aos
caracteres permitidos na lesma, para que o Little Bobby TABLES não
lhe faça uma visita indesejada.
Portanto, você deseja uma validação de formato de expressão regular no atributo de modelo User#slug
, mas também deseja poder usar a mesma expressão regular para
corresponder a um segmento de caminho em seu arquivo de rotas. Eu faço isso usando uma constante para a expressão regular de formato não
ancorado na parte superior do meu modelo:
class User < ActiveRecord::Base
SLUG_FORMAT = /([[:lower:]]|[0-9]+-?[[:lower:]])(-[[:lower:]0-9]+|[[:lower:]0-9])*/
# ...
Em seguida, adiciono uma validação ActiveModel no slug
campo e adiciono ancoragem
para tornar a validação do campo do modelo segura n
e outras
entradas furtivas que escapariam de um validador de formato não ancorado:
validates :slug, uniqueness: {case_sensitive: false},
format: {with: Regexp.new('A' + SLUG_FORMAT.source + 'z')}
Observe o uso das classes de caracteres RegExp A
e z
para o início e o
final da string, não ^
, $
ou Z
. Você pode ler os
documentos do RegExp
para entender as diferenças, mas a essência é essa A
e z
significa
exatamente o início e o fim de uma string, ponto final. Os outros correspondem a diferentes
pontos de ancoragem em uma string.
Agora, como armazenei a versão não ancorada da expressão regular de formato em
uma constante, posso usar essa mesma constante em meu arquivo de rotas:
constraints(slug: User::SLUG_FORMAT, id: /d+/) do
get '/users/:slug' => 'users#show', as: 'user'
end
Agora, se eu decidir mudar o formato de minhas lesmas permitidas, só preciso
mudá-lo em um lugar: minha SLUG_FORMAT
constante. Existem outras coisas sofisticadas que
você pode fazer com os slugs, como gerá-los automaticamente a partir de um name
campo e testar
seu comportamento por completo, mas vou deixar isso para outra hora.