Introdução a validações com Ruby on Rails

Neste artigo veremos que recursos o framework Rails oferece a fim de validar atributos dos objetos antes que eles sejam persistidos na base de dados.

A validação de informações em um sistema é uma tarefa realmente importante a fim de evitar que dados inconsistentes sejam armazenados no banco de dados. Por isso o framework Ruby On Rails oferece no módulo ActiveRecord, que é responsável não apenas pela persistência de objetos, mas também dispõe de recursos a fim de validar as informações antes de serem salvas.

A fim de que o leitor possa acompanhar os exemplos apresentados durante esse artigo é necessário ter no computador o ruby bem como o framework rails instalado. Durante todo o artigo faremos uso da ferramenta rails console que simula a aplicação executando, ou seja, essa ferramenta permite que executemos funcionalidades da aplicação sem acessá-la necessariamente pelo navegador, apenas por meio da linha de comando ou terminal. Por isso o tópico seguinte não deve ser deixado de lado caso deseje executar os exemplos na sua própria máquina, ele apresenta os passos necessário para a configuração do ambiente.

Instalação

Antes de instalar o Rails propriamente dito é necessário antes instalar o Ruby. Neste artigo partiremos do princípio que ambos estão instalados em sua máquina.

O teste para validar se a instalação do framework e da linguagem ocorreu corretamente pode ser feito digitando no terminal o comando apresentado a seguir:

rails –version => Rails 4.2.4

ou somente

rails -v => Rails 4.2.4

Essa instrução também deve mostrar como resultado a versão do Rails que foi instalada, caso outro resultado seja apresentado reveja os passos de instalação.

Criando o Projeto

Vamos criar um projeto Rails para aplicar alguns exemplos de validações. Para isso escolha um diretório em que deseja guardar o projeto, depois navegue até esse diretório através do terminal ou prompt de comando. Veja na Listagem 1 o comando para a criação de um projeto Raills chamado testes_validacoes. Esse comando cria toda a estrutura da aplicação conforme pode ser observado na saída.

~/RailsProjectsnbsp;railsnewtestes_validacoes createREADME.rdoc createRakefile createconfig.ru create.gitignore createGemfile createapp [...] createapp/controllers/application_controller.rb createapp/views/layouts/application.html.erb createapp/mailers/.keep createapp/models/.keep createapp/controllers/concerns/.keep createapp/models/concerns/.keep [...] runbundleinstall
Listagem 1. Comando de criação de uma aplicação Rails

Todas as aplicações Rails são baseadas na arquitetura MVC (modelo, visão e controle). As visões são as páginas da aplicação elas ficam armazenadas na página app/views, os controladores ficam na pasta app/controllers e os modelos na app/models esse último diretório é o que nos interessa já que as validações ficam nessas classes modelos que estendem ActiveRecord::Base do framework Rails.

Para continuar o exemplo vamos fazer uso dos geradores do Rails criando um modelo a fim de usar os validadores. A classe representará os clientes da aplicação os atributos serão nome, e-mail, telefone e endereco. Veja na Listagem 2 o comando para criação da classe Cliente com seus respectivos atributos e tipos. Note que esse comando deve ser executado dentro do diretório da aplicação criado no passo anterior.

~/RailsProjects/testes_validacoes array3 nbsp;railsgeneratemodel Clientenome:stringemail:stringtelefone:stringendereco:string invokeactive_record createdb/migrate/20151226122329_create_clientes.rb createapp/models/cliente.rb invoketest_unit createtest/models/cliente_test.rb createtest/fixtures/clientes.yml
Listagem 2. Comando para criação do modelo Usuário

Perceba que a saída gerada pelo comando acima inclui um arquivo com o nome [data_de_criação]_create_clientes.rb localizado na pasta db/migrate. Esse arquivo é responsável por criar no banco de dados da aplicação a tabela que armazenará os clientes. O conteúdo do arquivo gerado é semelhante ao apresentado na Listagem 3. O método change usa a instrução create_table para criar uma tabela clientes com os atributos que foram passados para o gerador do Rails.

class CreateClientes < ActiveRecord::Migration def change create_table :clientes do |t| t.string :nome t.string :email t.string :telefone t.string :endereco t.timestamps null: false end end end
Listagem 3. Conteúdo do arquivo de migração db/migrate/xxxx_create_clientes.rb

Caso as configurações de acesso a banco de dados não sejam alteradas, o Rails por padrão usará o sqlite. Essas configurações estão descritas no arquivo config/database.yml que deve ter o conteúdo parecido a Listagem 4. Note que o arquivo descreve onde ficará armazenado e como se chamará o banco de dados para os três ambiantes da aplicação, desenvolvimento, testes e produção.

development: database: db/development.sqlite3 test: database: db/test.sqlite3 production: database: db/production.sqlite3
Listagem 4. Conteúdo do arquivo config/database.yml

Para criar o banco de dados basta executar o comando mostrado a seguir:

~/RailsProjects/testes_validacoesnbsp;rakedb:create

Após a criação da base de dados é possível criar a tabela de clientes da aplicação, para isso basta executar o comando descrito na Listagem 5. Note que a saída do comando faz referência ao arquivo de migração xxxx_create_clientes.rb, esse arquivo foi usado para executar a criação da estrutura da tabela.

~/RailsProjects/testes_validacoesnbsp;rakedb:migrate ==20151226122329CreateClientes:migrating=================================== --create_table(:clientes) ->0.0032s ==20151226122329CreateClientes:migrated(0.0034s)==========================
Listagem 5. Comando para execução das migrações

Além do arquivo de migração outro arquivo criado pela execução do gerador foi app/models/cliente.rb, esse é o arquivo que será usado para inserir as instruções a respeito da validação dos atributos. O conteúdo, depois da geração do mesmo, deve ser igual ao exibido a seguir:

class Cliente < ActiveRecord::Base end

Validações

O módulo ActiveRecord do Rails oferece muitos validadores já prontos que podem ser usados nas classes de modelo para validar os dados informados nos atributos. É possível validar por exemplo um campo obrigatório, o formato de um valor, a confirmação de determinado campo, o tamanho, entre outras opções. As seções a seguir analisam algumas dessas opções de validação disponíveis.

Presence

Essa estrutura indica que o atributo é obrigatório e deve ser informado, ou seja, não pode ficar em branco. Veja a Listagem 6 o uso desses modificadores na classe Cliente para tornar os atributos nome, email e telefone obrigatórios.

class Cliente < ActiveRecord::Base validates_presence_of :nome validates_presence_of :email validates_presence_of :telefone end
Listagem 6. Uso do atributo validates_presence_of para tornar atributos obrigatórios

Podemos verificar o efeito desses modificadores usando o rails console. Essa ferramenta permite executar algumas operações como se a aplicação estivesse rodando em um servidor, mas sem interface gráfica, apenas pelo terminal ou linha de comando. Para iniciar esse instrumento basta digitar o comando exibido na Listagem 7, dentro do diretório da aplicação, assim que o comando é executado o ambiente de desenvolvimento é carregado e o console fica aguardando que códigos ruby para interpretá-los.

~/RailsProjects/testes_validacoesnbsp;railsconsole Loadingdevelopmentenvironment(Rails4.2.4) irb(main):001:0>
Listagem 7. Iniciando a ferramenta rails console

A Listagem 8 mostra um bloco de código que instância um objeto do tipo Cliente e não informa nada nos seus atributos, ou seja, eles estão vazios.

~/RailsProjects/testes_validacoesnbsp;railsconsole Loadingdevelopmentenvironment(Rails4.2.4) irb(main):001:0>cliente1=Cliente.new =># irb(main):002:0>cliente1.valid? =>false
Listagem 8. Código Ruby On Rails para instanciar um objeto do tipo Cliente

Note ainda na Listagem 8 que todos os atributos do objeto cliente1 estão com valores nil, ou nulos, mas foi definido anteriormente que os atributos nome, email e telefone não poderiam ser nulos ou vazios. Por isso quando o método valid? chamado no objeto cliente1 na linha 2 foi usado ele retornou false, exatamente pelo fato de que alguns atributos não passaram na validação. Isso pode ser comprovado por acessamos o método errors do objeto cliente1 que retorna os erros de validação que impedem que este usuário seja válido. Veja na Listagem 9 o uso do método errors para exibir os erros de validação de um objeto do tipo Cliente.

~/RailsProjects/testes_validacoesnbsp;railsconsole Loadingdevelopmentenvironment(Rails4.2.4) irb(main):001:0>cliente1=Cliente.new =># irb(main):002:0>cliente1.valid? =>false irb(main):003:0>cliente1.errors.full_messages.eachdo|mensagem_de_erro| irb(main):004:1*putsmensagem_de_erro irb(main):005:1>end
Listagem 9. Código para exibir erros de validação de um objeto
=>Nome can't be blank =>Email can't be blank =>Telefone can't be blank

O código da Listagem 9 teve como saída três mensagens de erro informando que os campos nome, email e telefone não podem ser deixados em branco ou vazios. Perceba, porém, que as mensagens padrão apresentadas estão em inglês. Caso seja necessário alterar essas mensagens, isso pode ser feito através da opção :message. Veja na Listagem 10 como ficaria a classe Cliente personalizando as mensagens de erro.

class Cliente < ActiveRecord::Base validates_presence_of :nome, message: 'não pode ser deixado em branco' validates_presence_of :email, message: 'não pode ser deixado em branco' validates_presence_of :telefone, message: 'não pode ser deixado em branco' end
Listagem 10. Exemplo de uso da opção message para personalizar mensagens de erro

Essas mudanças personalizam as mensagens de erro como é apresentado na Listagem 11.

nbsp;vimapp/models/cliente.rb daniel@brenda-compaq:~/RailsProjects/testes_validacoes ~/RailsProjects/testes_validacoesnbsp;railsconsole Loadingdevelopmentenvironment(Rails4.2.4) irb(main):001:0>cliente1=Cliente.new =># irb(main):002:0>cliente1.valid? =>false irb(main):003:0>cliente1.errors.full_messages.eachdo|e| irb(main):004:1*putse irb(main):005:1>end
Listagem 11. Exibindo mensagens de erro personalizadas
=>Nome não pode ser deixado em branco =>Email não pode ser deixado em branco =>Telefone não pode ser deixado em branco

Length

Esta instrução valida o tamanho ou a quantidade de caracteres do valor informado para os atributos. Existem muitas opções disponíveis que podem seu usadas juntamente com length para manter a consistência dos dados informados, entre elas estão.

Veja um exemplo de uso da estrutura length para definir tamanho máximo e mínimos para atributos da classe Cliente na Listagem 12.

class Cliente < ActiveRecord::Base validates_presence_of :nome, message: 'não pode ser deixado em branco' validates_presence_of :email, message: 'não pode ser deixado em branco' validates_presence_of :telefone, message: 'não pode ser deixado em branco' validates_length_of :nome, minimum: 2, message: 'deve ter pelo menos 3 caracteres' validates_length_of :email, minimum: 10, message: 'deve ter pelo menos 10 caracteres' validates_length_of :telefone, maximum: 11, message: 'deve ter até 11 caracteres' validates_length_of :endereco, in: 10..100, message: 'deve ter entre 10 e 100 caracteres' end
Listagem 12. Exemplo de uso da instrução length para validar atributos da classe Cliente

Agora note na Listagem 13 que os erros com relação a obrigatoriedade dos campos nome, email e endereço não mais aparecem quando eles são preenchidos. No entanto os erros que dizem respeito a quantidade de caracteres informadas para os atributos passam a reclamar caso os limites definidos não sejam obedecidos.

~/RailsProjects/testes_validacoesnbsp;railsconsole Loadingdevelopmentenvironment(Rails4.2.4) irb(main):001:0>cliente1=Cliente.new =># irb(main):002:0>cliente1.nome='an' =>"an" irb(main):003:0>cliente1.email='an@gmail' =>"an@gmail" irb(main):004:0>cliente1.telefone='889999999999' =>"889999999999" irb(main):005:0>cliente1.valid? =>false irb(main):006:0>cliente1.errors.full_messages.eachdo|mensagem| irb(main):007:1*putsmensagem irb(main):008:1>end
Listagem 13. Exibindo erros de validação por conta de tamanho de caracteres dos atributos
=> Nome deve ter pelo menos 2 caracteres => Email deve ter pelo menos 10 caracteres => Telefone deve ter até 11 caracteres => Endereco deve ter entre 10 e 100 caracteres

Uniqueness

Essa estrutura permite validar um campo que deve ser único, ou não pode se repetir como um CPF ou e-mail. Ele é usado para evitar que essas informações únicas não sejam duplicadas no banco de dados. Antes de inserir ou atualizar um registro no banco de dados uma pesquisa ou busca é feita a fim de saber se já há um registro com igual valor. A Listagem 14 apresenta o uso do validador validates_uniqueness_of para o atributo e-mail, veja.

class Cliente < ActiveRecord::Base validates_presence_of :nome, message: 'não pode ser deixado em branco' validates_presence_of :email, message: 'não pode ser deixado em branco' validates_presence_of :telefone, message: 'não pode ser deixado em branco' validates_length_of :nome, minimum: 2, message: 'deve ter pelo menos 2 caracteres' validates_length_of :email, minimum: 10, message: 'deve ter pelo menos 10 caracteres' validates_length_of :telefone, maximum: 11, message: 'deve ter até 11 caracteres' validates_length_of :endereco, in: 10..100, message: 'deve ter entre 10 e 100 caracteres' validates_uniqueness_of :email, message: 'deve ser único' end
Listagem 14. Uso de validates_uniqueness_of no atributo email da classe Cliente

A Listagem 15 mostra um exemplo do que acontece ao persistir um objeto cliente após ter inserido a validação de e-mail único. Note que antes de executar o comando INSERT no banco de dados uma consulta SELECT é feita procurando pelo e-mail do cliente que está tentando ser cadastrado. Se essa consulta retornar algum valor significa que já existe um registro com aquele e-mail, caso contrário a validação passa e o registro é persistido com sucesso.

~/RailsProjects/testes_validacoesnbsp;railsconsole Loadingdevelopmentenvironment(Rails4.2.4) irb(main):001:0>cliente1=Cliente.new =># irb(main):002:0>cliente1.nome='JosédaSilvaFilho' =>"JosédaSilvaFilho" irb(main):003:0>cliente1.email='jose.silva@gmail.com' =>"jose.silva@gmail.com" irb(main):004:0>cliente1.telefone='88997926700' =>"88997926700" irb(main):005:0>cliente1.endereco='RuadoJosédaSilva,Nº123' =>"RuadoJosédaSilva,Nº123" irb(main):006:0>cliente1.save (0.3ms)begintransaction
Listagem 15. Exemplo de código persistindo um objeto com validação uniqueness
Cliente Exists (0.3ms) SELECT 1 AS one FROM "clientes" WHERE "clientes"."email" = 'jose.silva@gmail.com' LIMIT 1 SQL (35.3ms) INSERT INTO "clientes" ("nome", "email", "telefone", "endereco", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["nome", "José da Silva Filho"], ["email", "jose.silva@gmail.com"], ["telefone", "88997926700"], ["endereco", "Rua do José da Silva, Nº 123"], ["created_at", "2015-12-27 18:53:05.731692"], ["updated_at", "2015-12-27 18:53:05.731692"]] (66.2ms) commit transaction => true

Numericality

Essa instrução valida como o próprio nome diz, valores numéricos. Imagine que a classe Cliente passasse a ter um atributo idade, validates_numericality_of poderia ser usado para evitar que valores não numéricos fossem armazenados, como apresentado na Listagem 16.

class Cliente < ActiveRecord::Base validates_presence_of :nome, message: 'não pode ser deixado em branco' validates_presence_of :email, message: 'não pode ser deixado em branco' validates_presence_of :telefone, message: 'não pode ser deixado em branco' validates_length_of :nome, minimum: 2, message: 'deve ter pelo menos 2 caracteres' validates_length_of :email, minimum: 10, message: 'deve ter pelo menos 10 caracteres' validates_length_of :telefone, maximum: 11, message: 'deve ter até 11 caracteres' validates_length_of :endereco, in: 10..100, message: 'deve ter entre 10 e 100 caracteres' validates_uniqueness_of :email, message: 'deve ser único' validates_numericality_of :idade, message: 'deve ser um número' end
Listagem 16. Exemplo de uso da estrutura validates_numericality_of

Combinando validadores

Perceba nos exemplos acima que os atributos foram repetidos em várias linhas para validações diferentes. Isso pode ser evitado usando a estrutura validates onde é possível combinar duas ou mais instruções validadoras. Veja na Listagem 17 o uso de validates combinando várias validações para os atributos da classe Cliente.

class Cliente < ActiveRecord::Base validates :nome, presence: {message: 'não pode ser deixado em branco'}, length: {minimum: 2, message: 'deve ter pelo menos 2 caracteres'} validates :telefone, presence: {message: 'não pode ser deixado em braco'}, length: {maximum: 11, message: 'deve ter até 11 caracteres'} validates :email, presence: {message: 'não pode ser deixado em branco'}, length: {minimum: 10, message: 'deve ter pelo menos 10 caracteres'}, uniqueness: {message: 'deve ser único'} validates :endereco, length: {in: 10..100, message: 'deve ter entre 10 e 100 caracteres'} end
Listagem 17. Usando validates para combinar tipos de validações

Esse artigo abordou as principais formas de validação disponíveis no framework Ruby On Rails. Essas estruturas agilizam o trabalho para o desenvolvedor para que este concentre-se mais nas regras de negócio do que em trabalhos repetitivos como validação de dados.

Artigos relacionados