length: quatro formas para uma opção

Prévia grátis 3 min de leitura

Dois cursos anteriores apontaram para cá

Em ActiveRecord: introdução ao model, a aula "Validações: uma regra antes de salvar" apresentou validates como uma regra que o Rails confere antes de salvar um registro. Ela terminava dizendo que as opções, as formas de uma checagem falhar e o jeito de mostrar falhas ao usuário ganhariam um curso próprio. Em ActiveRecord: criando registros, a aula "Quando save retorna false" foi um passo além. Ela mostrou .save devolvendo false quando uma validação falha e article.errors.full_messages explicando o motivo, e apontou para o mesmo curso. Aquele curso também tratou de .save! e .create! levantando ActiveRecord::RecordInvalid, então este não repete o assunto.

Este é esse curso. Ele começa por uma opção que dois models deste projeto já usam: length.

length já tem duas formas neste código

# de Identity::User, o modelo real deste projeto
validates :username, presence: true,
                     uniqueness: { case_sensitive: false, message: "is not available" },
                     length: { minimum: 3, maximum: 30 },
                     format: { with: /\A[a-zA-Z0-9_]+\z/ }

length: { minimum: 3, maximum: 30 } rejeita um username com menos de 3 caracteres ou mais de 30. São dois limites separados no mesmo atributo. Catalog::Course e Catalog::Lesson usam a forma mais simples, com um limite só:

# de Catalog::Course, o modelo real deste projeto
validates :title_en, presence: true, length: { maximum: 255 }

Aqui há limite superior e nenhum inferior. As duas linhas usam a mesma opção length:, com chaves diferentes.

Mais duas formas, testadas numa tabela de rascunho

Nem in: nem is: aparecem neste código hoje. in: recebe um range que define os dois limites de uma vez, e is: exige um comprimento exato. Veja os dois num model descartável, ScratchArticle, criado para esta aula:

class ScratchArticle < ApplicationRecord
  validates :title, length: { in: 3..20 }
  validates :code, length: { is: 4 }
end

a = ScratchArticle.new(title: "ab")
a.valid?
a.errors[:title]
# => ["is too short (minimum is 3 characters)"]

b = ScratchArticle.new(title: "a" * 25, code: "abc")
b.valid?
b.errors[:title]
# => ["is too long (maximum is 20 characters)"]
b.errors[:code]
# => ["is the wrong length (should be 4 characters)"]

in: 3..20 é minimum: 3, maximum: 20 escrito como um range só, com as mesmas falhas e as mesmas mensagens. is: 4 é mais rígido que os dois. Não é um range: o valor tem um único comprimento permitido.

Quatro chaves, uma opção

minimum, maximum, in e is pertencem todos à mesma opção length:; não são quatro validações diferentes. O model escolhe a forma que combina com a regra: só um limite superior, como o título de Catalog::Course; os dois limites, como o username de Identity::User; um range escrito num valor só; ou um comprimento exato, para algo como um código de tamanho fixo.

O Rails lê as chaves presentes. A mensagem diz qual limite falhou ("too short", "too long", "the wrong length") em vez de um "invalid" genérico.

Pontos-chave

  • ActiveRecord: introdução ao model apresentou validates, e ActiveRecord: criando registros mostrou .save devolvendo false com .errors.full_messages explicando o motivo. Este curso continua de onde os dois pararam.
  • length: { minimum:, maximum: } em Identity::User e length: { maximum: } em Catalog::Course são a mesma opção com chaves diferentes.
  • in: (um range) e is: (um comprimento exato) não aparecem neste código. Numa tabela de rascunho, in: 3..20 se comporta como minimum: 3, maximum: 20, e is: 4 aceita só aquele comprimento.
  • Cada forma tem sua mensagem de erro ("too short", "too long", "the wrong length"), que você lê em .errors[:attribute].
Aula 1 de 7 · grátis

Continue com a aula 2

uniqueness: com escopo, e sem diferenciar maiúsculas de propósito

Unicidade dentro de um grupo com scope:, sem diferenciar maiúsculas com case_sensitive: false, e mensagem própria com message:.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...