Rails básico: MVC, scaffold e migrations

Neste post vamos implementar um aplicativo de agenda de contatos pessoal bem simples, mas vamos conseguir explorar algumas funcionalidades interessantes deste framework. Caso tenha dúvidas ou problemas sobre a instalação do Rails, dê uma olhada no post anterior Rails: instalando e executando! (Linux).

Só para avisar que este post é um tutorial bem básico sobre Rails, então quem não sabe nada ainda sobre o framework vai aproveitar bastante.

Definindo as funcionaldiades

Como o nosso aplicativo é bem simples, vamos definir algumas poucas funcionalidades: como dono da agenda eu preciso cadastrar, editar, ver e remover contatos da agenda, ou seja um CRUD (Create, Retrieve, Update e Delete) de contatos. Cada contato deve possuir, por enquanto, apenas um Nome e um Número de Telefone. Para simplificar vamos tratar os dois como string.

O primeiro passo é criar a aplicação Rails, para tanto vá na pasta do seu workspace e execute o comando:

$>rails new minha_agenda -d=mysql
$>cd minha_agenda/

A opção ‘-d=mysql’ diz para utilizar como banco de dados o MySQL, caso não queira utilizá-lo, basta não adicionar a opção que será utilizado o banco SQLite padrão de aplicações Rails.

Após a criação do app execute ‘rails server’ para verificar se tudo está funcionando. Acesse http://localhost:3000/ e você deverá ver a página de boas vindas do Rails.

Caso tenha algum problema durante a execução de algum comando, verifique no arquivo ‘Gemfile’ na raiz do projeto se as gems ‘therubyracer’ e ‘execjs’ estão incluídas, caso contrário inclua:

gem 'execjs'
gem 'therubyracer'

Certo, agora que tudo está funcionando, vamos criar o nosso contato. Para isto vamos utilizar o comando ‘scaffold’, que como a palavra diz, serve como um andaime para a nossa aplicação. Este comando gera os arquivos seguindo a arquitetura de aplicativos Rails, ou seja, ele cria um arquivo de modelo, controlador, helper e as views necessárias. Para entender melhor, vá na raiz do projeto e execute o comando:

$>rails generate scaffold Contato nome:string telefone:string

O comando completo é ‘rails generate scaffold’, em seguida temos o nome da entidade, no caso o ‘Contato’ e em seguida os atributos seguidos dos seus tipos ‘nome:string telefone:string’.

Vamos entender um pouco sobre a arquitetura da aplicação Rails, observe a imagem a seguir:

A organização do aplicativo segue o padrão MVC, ou seja, separa a entidade em Modelo (na pasta ‘app/models’), Visão (na pasta ‘app/views’) e Controlador (na pasta ‘app/controllers’). O usuário interage através do browser, enviando uma requisição, geralmente HTTP. Esta requisição será tratado no controlador, que vai interagir com os dados do modelo para então gerar a visualização com as informações. Um vez pronta, a visualização poderá ser renderizada pelo browser, como HTML por exemplo.

Criando o banco de dados

Vamos botar o aplicativo para funcionar e entender melhor. Primeiro precisamos criar os bancos de dados, execute, na raiz do projeto, o comando:

$>rake db:create:all

Esta tarefa rake vai criar as bases de dados necessários para o aplicativo, ou seja a base de desenvolvimento, testes e produção. Agora precisamos criar a tabela que vai armazenar os Contatos, para isso vamos criar uma migração. No Rails, uma migração é uma modificação na base de dados. Desta maneira você não precisa sair alterando manualmente as tabelas de todas as bases de dados, ou escrever consultas diretamente.

Ao executar o comando scaffold, a migração já será criada, verifique a pasta ‘db/migrate’, nela ficam salvas todas as migrações. Cada migração possui um timestamp na frente do arquivo (para indicar quando a migração foi criada) e depois um ‘_’ seguido da descrição da migração, no meu caso o arquivo ficou ‘20120216141302_create_contatos.rb’.

Abra o arquivo e veja que ele consiste de uma classe que herda de ActiveRecord::Migration e define um método chamado ‘change’. Neste método encontram-se as modificações a serem feitas. Para os Contatos, o arquivo deve estar assim:

class CreateContatos < ActiveRecord::Migration   def change     create_table :contatos do |t|       t.string :nome       t.string :telefone       t.timestamps     end   end end 

Criamos então a tabela contatos com as colunas nome e telefone do tipo string. Além disso o Rails utiliza internamente um timestamp em todas as tabelas. Não é necessário inserir explicitamente um id para as tabelas, o rails fará isto para você automaticamente. Vamos então executar a migração para adicionar os dados ao banco:

 $>rake db:migrate
==  CreateContatos: migrating =================================================
-- create_table(:contatos)
   -> 0.1304s
==  CreateContatos: migrated (0.1306s) ========================================

Pronto, o banco de dados já possui espaço para as informações, agora podemos ver o aplicativo funcionando, rode o server e acesse a página http://localhost:3000/contatos.

$>rails server

Esta página é gerada automaticamente pelo comando scaffold, veremos mais detalhes quando chegar na parte da view, por enquanto, basta ver que tudo está funcionando. É possível adicionar, listar, editar e apagar contatos, ou seja, todo o CRUD de Contatos é gerado automaticamente pelo scaffold.

Model

Vamos entender melhor como tratar o modelo, abra o arquivo de modelo dos contatos ‘app/models/contato.rb’. Neste arquivo vamos adicionar as regras do nosso modelo, por exemplo, podemos garantir que os campos Nome e Telefone sejam preenchidos obrigatoriamente.

class Contato < ActiveRecord::Base   validates_presence_of :nome, :message => " - Deve ser preenchido"
  validates_presence_of :telefone, :message => " - Deve ser preenchido"
end

Utilizando os validadores no modelo fica bem fácil garantir a integridade dos dados. Antes poderíamos criar um contato totalmente vazio, agora, ao tentar submeter o formulário de criação, será exibido as mensagens de validação. Volte em http://localhost:3000/contatos e tente criar um contato vazio para verificar que a validação realmente ocorreu.

Existem vários tipos de validadores, inclusive você pode criar seu próprio validador, mas por enquanto vamos deixar assim.

Controller

O controlador recebe a requisição HTTP do browser e direciona para a view específica. Ao abrir o arquivo ‘contatos_controller.rb’ na pasta ‘app/controllers’ você verá que existem sete métodos, e acima de cada um está um comentário explicando o que cada um faz, analisando o método ‘index’ por exemplo:

  # GET /contatos
  # GET /contatos.json
  def index
    @contatos = Contato.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @contatos }
    end
  end

Ao receber um ‘GET /contatos’, o controlador vai executar o método ‘index’, ou seja, quando acessamos http://localhost:3000/contatos, este método é que será executado. Aqui é criada uma variável ‘@contatos’ que vai armazenar a lista de todos os contatos, através da chamada do método ‘all’ de ‘Contato’. Em seguida o método executa a resposta, dependendo do formato, se acessar através de HTML, com o ‘GET /contatos’ devolve um HTML, como o comentário indica, o index.html.erb. Caso acesse ‘GET /contatos.json’ será retornado um json.

Todos os outros métodos do controlador seguem a mesma ideia e possuem comentários que ajudam a entender cada um deles. O importante aqui é notar a variável de instância @contatos (variáveis sem o ‘@’ na frente são variáveis apenas locais), ela estará disponível na view index, por isso ela precisa armazenar a lista de contatos.

View

Abra então o arquivo ‘index.html.erb’ na pasta ‘app/views/contatos’ note que ele é um arquivo com marcações HTML e pedaços de código Ruby, por isso o formato .erb, ou embedded ruby. As tags <% %> indicam código ruby que deve ser apenas executado, já a tag <%= %> indica que o retorno deste código ruby deve ser renderizado na página.

A view index possui uma tabela com a listagem de contatos, como mostra o código a seguir:

<h1>Listing contatos</h1>

<%= hello %>

<table>
  <tr>
    <th>Nome</th>
    <th>Telefone</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @contatos.each do |contato| %>
  <tr>
    <td><%= contato.nome %></td>
    <td><%= contato.telefone %></td>
    <td><%= link_to 'Show', contato %></td>
    <td><%= link_to 'Edit', edit_contato_path(contato) %></td>
    <td><%= link_to 'Destroy', contato, confirm: 'Are you sure?', method: :delete %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New Contato', new_contato_path %>

A parte ‘<% @contatos.each do |contato| %>’ é semelhante ao foreach de outras linguagens, mas devido aos blocos funcionais do Ruby, não é necessário utilizar o foreach. Aqui, todos os contatos são percorridos, utilizando a variável definida no controller, e mostrados numa tabela, utilizando a variável local ‘contato’, definida no ”. Ao lado dos dados são também exibidos os botões para exibir (‘Show’), editar (‘Edit’) e remover (‘Destroy’) o contato da linha. No final do arquivo é exibido o botão para criar um novo contato (‘New Contato’).

Os botões utilizam o método ‘link_to’ que adiciona um link para uma ação, por exemplo ‘link_to ‘Show’, contato’ é um link com nome ‘Show’ que redireciona para a página de exibição da variável ‘contato’. Os outros links utilizam outros parâmetros para realizar as operações, mas a ideia é a mesma.

Helper

O Rails utiliza também os helpers, que não estão descritos na imagem da arquitetura MVC. Helpers são módulos que auxiliam as views. De maneira prática, nos helpers são definidos métodos que poderão ser invocados na view. Para exemplificar, abra o arquivo ‘contatos_helper.rb’ na pasta ‘app/helpers’ e adicione o seguinte método:

module ContatosHelper

  def hello
    "Hello World"
  end

end

Lembre que em Ruby a última linha é considerada o retorno do método. Agora, abra a view index (arquivo ‘index.html.erb’ na pasta ‘app/views/contatos’) e adicione:

<h1>Listing contatos</h1>

<%= hello %>

Ao recarregar a view, você verá a mensagem Hello World no local onde você adicionou o código. Geralmente os métodos dos helpers ajudam na formatação da página, por exemplo converter um float em unidade monetária.

Nos próximos posts vamos analisar outros pontos básicos do Rails que permitem um desenvolvimento rápido para WEB. 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! 😀

10 comentários sobre “Rails básico: MVC, scaffold e migrations

  1. Tive que atualizar o ‘execjs’ e o ‘therubyracer’, usei o cmd:

    $ Gem install

    mas adorei a matéria!! bem esclarecida, melhor q meu professor!!!

    Abraços
    Anderson

  2. Rapaz, depois que eu vi a utilização do “scaffold” eu não acreditei. Eu estava seguindo o tutorial do rubyonrails.org e ele ensina a fazer o CRUD todinho, mas no modo braçal! Foi bom para aprender, mas eu demorei 2 dias para aprender a implementar o CRUD. Ótimo o scaffold poupa muuuito tempo. Ótimo tutorial, obrigado!

  3. Muito bom tutorial, me ajudou muito.
    Uma dúvida que tive no meio do caminho era como deletar um campo que adicionei no scaffold (um campo de data desnecessário, pois já é criado o campo timestamp, como você disse). Então encontrei o comando:
    rails g migraiton Remove..From.. col1:type col2:type col3:type

    no meu caso, removi o campo ‘data’ da tabela ‘cota’:
    rails g migration RemoveDataFromCota data:date

    Foi criado o arquvo migration com os dados:

    class RemoveDataFromCota < ActiveRecord::Migration
      def up
        remove_column :cota, :data
      end
      def down
        add_column :cota, :data, :date
      end
    end
    

    Daí só falta mandar o comando: rake db:migrate
    Pra ajudar as pessoas que terão a mesma dúvida que tive futuramente lendo seu tutorial. 😀

  4. Marcos, parabéns … Excelente o seu post. Voce tem algum tutorial sobre como usar o Jquery no Rails ?
    Estou precisando muito disso, tenho tentado e nao tenho obtido resultado.

    • Obrigado Jose, que bom que lhe foi útil.
      Sobre o jQuery, eu não escrevi nada sobre isso, mas acho que é bem simples – pelo que já usei. Basta que você coloque a lib dentro da pasta de assets e incluir na view com javascript_include_tag.

  5. Excelente postagem! Super explicativa, parabéns.

  6. Eu consigo gerar o scaffold tranquilo e sem erros, exceto o destroy! Eu não sei o que há, mas quando clico no destroy sou redirecionado para o index novamente!

  7. tenho um arquivo.sql, importo dentro do mysql crio o banco de dados, como inserir no meu projeto, para criar o mvc? tentei db:schema:dump mas não funcionou.

    • Oi Elizeu. A ideia das migrações é que você deixe o Rails gerenciar o estado do banco, se você já tem um .sql pra importar precisa gerar um novo arquivo de schema.rb pro Rails saber como lidar com esse banco.

Deixe um comentário