Rails básico (cont.): helpers, validações, migrations e partial

Continuando a série de posts sobre Rails, vamos dar uma olhada em mais alguns recursos básicos da linguagem. Se você não viu o post anterior, então dê uma olhada aqui: Rails básico: MVC, scaffold e migrations, pois vamos utilizar o projeto inicialmente construído.

Um pouco mais sobre helpers

No post anterior vimos o que são helpers e como eles podem atuar de maneira prática. Vamos então utilizar o helper dos contatos para formatar o número do telefone dos nossos contatos. Primeiro rode o servidor (‘rails server’) e adicione algum contato na agenda, lembre de utilizar um número de telefone válido, no caso que tenha os dois dígitos do DDD e os oito dígitos do número em si(mais na frente vamos ver como garantir isso).

Note como fica o número do telefone. Seria interessante adicionarmos os parênteses no DDD por exemplo, ou colocar um hífen separando o 4 primeiros e 4 últimos dígitos. Vamos então criar um método no helper para formatar o número, este método vai receber uma string como parâmetro, que será a string do número do telefone, e vai formatá-la da seguinte forma: (##)####-####. Abra então o arquivo ‘contatos_helper.rb’ na pasta ‘app/helpers’ e adicione o método:

  def formata_telefone(n_telefone)
    tel_formatado = "("
    tel_formatado << n_telefone[0..1]
    tel_formatado << ")"
    tel_formatado << n_telefone[2..5]
    tel_formatado << "-"
    tel_formatado << n_telefone[6..9]
    tel_formatado
  end

Este método é uma solução bem simples, criamos uma nova string e copiamos o conteúdo para um nova string formatada. Ao utilizar, por exemplo ‘n_telefone[2..5]’ estamos extraindo os caracteres iniciando na casa 2 até a casa 5 da string ‘n_telefone’. O operador ‘<<' faz um append na string, como se fosse o append do StringBuilder no java.

Com o método pronto, basta fazer a chamada ao método nas views dos contatos. Abra então o arquivo 'index.html.erb' na pasta 'app/views/contatos' e altere o código onde é exibido o número do telefone:

...
<% @contatos.each do |contato| %>
  <tr>
    <td><%= contato.nome %></td>
    <td><%= formata_telefone(contato.telefone) %></td>
...

Agora adicione também o código na view show. Abra o arquivo 'show.html.erb' na mesma pasta e altere o código:

...
  <b>Telefone:</b>
  <%= formata_telefone(@contato.telefone) %>
...

Pronto, agora recarregue a página http://localhost:3000/contatos e você deverá ver os números formatados. Ao clicar no botão 'Show' de algum contato, também será exibido o número formatado.

Validação personalizada

Discutimos antes que o projeto como está permite adicionar qualquer string como número do telefone, além de não fazer nenhuma restrição ao tamanho do telefone. Vamos então criar algumas validações para verificar estas situações.

Como as validações devem estar nos arquivos do modelo, abra o arquivo ‘contato.rb’ na pasta ‘app/models’. Nele, devem estar até agora as validações de presença que adicionamos no post anterior, agora vamos criar nossa própria validação. Adicione o seguinte código dentro da classe:

  validate :eh_numero
  private
  def eh_numero
    errors.add("telefone", " - Deve ser um numero") unless telefone =~ /^[\d]+$/
  end

Aqui estamos dizendo que o Rails deve validar o método ‘eh_numero’. Dentro deste método estamos utilizando a estrutura ‘unless’ do Ruby, que executa a ação da esquerda, a menos que a condição da direita seja verdadeira.

Outro operador é o ‘=~’ que serve para comparar strings com expressões regulares, neste caso esta expressão apenas garante que a string deve ser formada de um ou mais números.

Então, a menos que a string ‘telefone’ seja formada por números, será adicionado um erro na pilha de erros do Rails, através da chamada a ‘errors.add()’.

Para testar se tudo funcionou, volte na página e tente adicionar como telefone uma string qualquer que contenha uma letra. Será então exibida a mensagem de erro no topo da tela.

Agora, precisamos garantir que a string tenha um tamanho de 10, para indicar um número de telefone. Vamos então adicionar outra validação, seguindo a mesma ideia do exemplo anterior:

 validate :tem_dez_digitos
...
  def tem_dez_digitos
    errors.add("telefone", " - Deve ter dez digitos") unless telefone.size == 10
  end

Aqui utilizamos a mesma estrutura, agora verificando se o tamanho do telefone é igual a 10. Tente agora adicionar um novo contato com menos de dez dígitos e a mensagem deverá ser exibida.

A ideia aqui foi mostrar como adicionar validadores personalizados, no entanto o Rails oferece vários validadores para evitar este trabalho. Um exemplo é o validador ‘validates_format_of’ que verifica o formato de uma string com uma expressão regular. Poderíamos então substituir o nosso validador personalizado por este, bastando apenas uma linha:

  validates_format_of :telefone, :with => /^[\d]+$/, :message => " - Deve ser um numero"

Outro validador que poderia nos poupar trabalho é o ‘validates_length_of’ que verifica o tamanho de uma string:

  validates_length_of :telefone, :is => 10, :message => " - Deve ter dez digitos"

Além do ‘:is’, este validador aceita parâmetros como ‘:maximum’, ‘:minimum’, ‘:in’, entre outros. Uma visita na página da API do Rails (http://apidock.com/rails/ActiveModel/Validations) vai lhe dar uma visão bem melhor sobre todas as validações do framework.

Um pouco mais sobre Migrations

No post anterior, vimos que o ‘scaffold’ cria uma migration para construir a tabela da entidade. Vamos então criar nossa própria migration. Para exemplificar, vamos supor que agora precisamos armazenar também os e-mails dos contatos, ou seja, vamos alterar a base de dados, e para isto precisamos utilizar uma migration. Vá na raiz do projeto e execute o comando:

$>rails generate migration add_column_email_contatos

Então, dentro da pasta ‘app/db/migrate’ será criado um arquivo com um timestamp seguido da descrição que adicionamos. No meu caso ficou assim: ‘20120217133753_add_column_email_contatos.rb’. Abra o arquivo e você verá que dois métodos estão criados, o ‘up’ e o ‘down’. O método ‘up’ é chamado para alterar a base de dados, já o método ‘down’ é chamado para desfazer a alteração na base de dados. Como queremos adicionar uma coluna, insira o código dentro da classe:

  def up
    add_column :contatos, :email, :string
  end

  def down
    remove_column :contatos, :email
  end

No método ‘up’ adicionamos na tabela contatos a coluna email que é uma string. Já no método ‘down’ removemos da tabela contatos a coluna email. Execute agora a migration, com o seguinte comando:

%>rake db:migrate

Se vocẽ acessar o banco de dados, verá que as mudanças foram feitas.

$> mysql -u root
mysql> use minha_agenda_development
mysql> describe contatos;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| nome       | varchar(255) | YES  |     | NULL    |                |
| telefone   | varchar(255) | YES  |     | NULL    |                |
| created_at | datetime     | NO   |     | NULL    |                |
| updated_at | datetime     | NO   |     | NULL    |                |
| email      | varchar(255) | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

No entanto, ao acessar as páginas, não existe nada sobre o campo ‘email’. Precisamos então alterar as views! Abra o aquivo ‘index.html.erb’ na pasta ‘app/views/contatos’ e adicione um ‘th’ com o nome ‘Email’ e um ‘td’ para exibir ‘contato.email’:

...
    <th>Nome</th>
    <th>Telefone</th>
    <th>Email</th>
...
    <td><%= contato.nome %></td>
    <td><%= formata_telefone(contato.telefone) %></td>
    <td><%= contato.email %></td>
...

Pronto, na view index será exibido o campo email dos contatos. Agora abra o arquivo ‘show.html.erb’ e adicione um ‘p’ para exibir o email, seguindo o modelo dos outros atributos:

...
<p>
  <b>Email:</b>
  <%= @contato.email %>
</p>
...

Pronto, agora a view show também exibe o email. No entanto, as views que contém formulários (new e edit) ainda não foram alteradas. Vamos ver então um pouco sobre partial.

Partial

Partial são fragmentos de códigos ‘.html.erb’ que podem ser incluídos na view. Assim é possível reutilizar visualizações. Todo partial começa com um ‘_’ e se você observar, na pasta ‘app/views/contatos’, existe um arquivo chamado ‘_form.html.erb’. Este arquivo é um partial que contém a visualização de um formulário de cadastro da entidade Contato e é chamado nas views new e edit.

Abra o arquivo ‘_form.html.erb’ e note que o campos são exibidos dentro de divs com a classe ‘field’. Adicione então uma nova div para exibir no formulário o campo email, seguindo o modelo dos outros atributos:

...
  <div class="field">
    <%= f.label :email %><br />
    <%= f.text_field :email %>
  </div>
...

Agora abra o arquivo ‘new.html.erb’ e veja que ele chama o método render, passando como parâmetro ‘form’ que é o nome do partial, sem o ‘_’. Este método vai então renderizar este partial dentro da página. A view edit também faz a mesma chamada. Portanto, ao alterar o partial ‘_form.html.erb’ será exibido o campo ‘email’ em ambas as views.

Fica como exercício agora aplicar as validações do campo e-mail. Um dica é procurar por expressões regulares (regex) pois facilita bastante o trabalho!

A partir deste pequeno exemplo é possível ver quão rápido é o desenvolvimento WEB com Rails. O foco aqui foi o lado servidor, por isso não fizemos nenhuma customização com CSS ou JavaScript nas views, no entanto este trabalho também é bem facilitado pelo Rails, basta pesquisar um pouco para encontrar várias Gems que oferecem recursos poderosos com JS, como validação no lado cliente, máscaras, etc.

Se gostou do post compartilhe com seus amigos e colegas, senão, comente o que pode ser melhorado. Encontrou algum erro no código? Comente também. Possui alguma outra opinião ou alguma informação adicional? Comenta ai! 😀

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s