Crie seu primeiro aplicativo de diário com Ruby on Rails
Criado por Piotr Szotkowski (chastell) e Tomasz Stachewicz (tomash)
Tradução PT-BR por (Ricardo Hiroyuki Eihara Junior)
Iremos criar desde o início uma pequena aplicação de votação usando o framework de desenvolvimento web para Ruby chamado Rails. Pense o que sua primeira aplicação deveria ser sobre - pode ser algo simples que inclua uma coleção de algo: por exemplo, uma lista de tarefas, um diário, etc. Usaremos o diário como base neste tutorial.
INSTRUTOR(A): Para saber mais sobre a razão por trás desse tutorial para iniciantes um pouco diferente, dê uma olhada em post.
Certifique-se que você tenha o Rails instalado. Siga o guia de instalação para estar preparado.
Conheça as ferramentas
Editor de Texto
- Atom, Sublime Text, Vim e Emacs são exemplos de editores de texto que você pode usar para escrever seu código e editar arquivos.
Terminal (Conhecido como Prompt de Comando no Windows)
- É onde você inicia o servidor do Rails e executa os comandos.
Navegador
- (Firefox, Safari, Chrome) para ver sua aplicação.
INSTRUTOR(A): Ajude com a instalação; garanta que o editor de texto esteja propriamente preparado (por exemplo, verifique se o encoding é UTF-8).
Importante
É importante que você siga as instruções específicas para o seu sistema operacional - os comandos que você precisa executar no Windows são um pouco diferentes do que no Mac ou Linux. Se você estiver tendo problemas verifique o Sistema Operacional embaixo dos comandos. No caso de utilizar um serviço cloud (por exemplo, nitrous), você precisa rodar os comandos do Linux mesmo estando em uma máquina com windows.
HTML Puro
Arquivos e Diretórios
Crie um novo diretório (pasta) e crie um arquivo com o nome de index.html
nele. Abra o arquivo no seu editor e no navegador.
INSTRUTOR(A): Explique que os navegadores podem abrir arquivos locais, apenas a URL que vai ficar estranha.
Estrutura do HTML
Comece adicionando uma estrutura para o seu HTML escrevendo o que está embaixo no arquivo index.html
:
INSTRUTOR(A): Explique as duas partes do HTML, <head>
e <body>
. Explique a tag <title>
e brevemente a tag <meta>
, <link>
e <script>
se necessário. Bootstrap está presente no projeto por isso o CSS pode ser pulado (a menos que os participantes queiram que você explique).
Primeiro conteúdo visto
Adicione o seguinte HTML entre as tags <body>
e </body>
(sinta-se livre para ajustar o conteúdo…):
Estes são seus três primeiros registros no diário. Note como são diferentes as tags mostradas e note a repetição da estrutura.
INSTRUTOR(A): Fale um pouco sobre as tags em HTML e sua semântica.
Mais HTML
Adicione o seguinte seja antes ou depois das entradas do diário acima (denovo, ajuste a seu gosto)
Este é uma lista não ordenada em HTML com alguns itens listados nos links com uma referência (URLs) para outras páginas. É seguido de um parágrafo contendo uma imagem - e a origem da imagem esta na URL dada.
INSTRUTOR(A): Explique como a Web funciona e fale um pouco sobre os elementos em HTML e seus atributos.
Aqui está um link de um repositório com um estilo basico para se usar na aplicação.
Mudando para o Rails
INSTRUTOR(A): Se os seus estudantes estão no Windows, considere utilizar o Nitrous.IO como base para as próximas partes.
Nova aplicação em Rails
Abra a janela do terminal (Prompt de Comando do Windows), mude para o diretório onde os seus arquivos estão (usando o comando cd
) e rode rails new diary
- ele vai levar um tempo e terminará criando uma nova aplicação do Rails. Execute cd diary
para mudar para o diretório da aplicação.
INSTRUTOR(A): Explique como navegar pelos diretórios e executar comandos.
Rodando o servidor
Uma vez dentro do diretório diary
execute rails server
e (quando ele terminar de começar) vá para http://localhost:3000 no seu navegador. Você deverá ver uma página de Bem-vindo a bordo
. Pare o servidor pressionando ctrl-c
.
INSTRUTOR(A): Explique o que aconteceu e o que são as saídas da janela do terminal. Se o servidor falhar em começar por causa do JavaScript runtime, gem install therubyracer
e descomente a linha relevante na Gemfile
.
Primeira rota e visão
Crie o controlador e a rota.
Execute rails generate controller welcome index
- ele vai gerar seu primeiro controlador e a rota que leva a ele. Inicie seu servidor e vá para http://localhost:3000 para ver que sua aplicação realmente vai para a rota /welcome/index
.
Pare o servidor e execute rake routes
para ver todas as rotas suportadas pela sua aplicação.
INSTRUTOR(A): Explique as URLs e a hierarquia da URL. Explique como o Rails mapeia as URLs e o que acontece por debaixo dos panos
.
Mova a visão para o topo do seu site
Edite o arquivo config/routes.rb
e descomente (remove o #
da frente) a linha root 'welcome#index'
(provavelmente será a sétima linha). Isso vai fazer com que a raiz da sua aplicação seja renderizada pela ação Welcome#index
. Vá para http://localhost:3000 e veja que realmente a página principal da sua aplicação agora serve aquele visão (diferente da página Bem-vindo a bordo
).
INSTRUTOR(A): Explique como a página principal da aplicação é a raiz da hierarquia das URLs e que é a página que as pessoas visitam quando apenas colocam o nome do hospedeiro na barra de endereço do navegador.
Mova de um HTML existente para a visão certa
Edite o arquivo app/views/welcome/index.html.erb
e copie seu conteúdo da tag <body>
do seu arquivo original index.html
(a sua lista de entradas do diário e links dos sites), trocando as duas linhas (com <h1>
e <p>
) na visão. Atualize o navegador e veja que a página agora contém o conteúdo correto.
INSTRUTOR(A): Explique que a visão apenas contém o que está em <body>
e </body>
, e que o resto é comum para toda a aplicação definida em outro lugar.
Iteração
Repetição de conteúdo
Se você olhar como é estruturado sua lista de links, parece que todo item da lista é similar aos outros - ele contém uma URL (o link que será levado quando clicar nele) e um nome (o que deveria ser quando o usuário ver e poder clicar nele). Melhor do que escrever os links em HTML puro (e potencialmente cometer algum erro em algum deles) vamos abstrair um pouco e iterar sobre uma coleção de pares de URLs e nomes.
Troque o conteúdo da tag <ul>
com o seguinte:
Atualize o navegador para ver se a página continua com os mesmos links.
INSTRUTOR(A): Explique o que aconteceu - o que é um array, o que <%
e <%=
tags do ERb significam (e como eles diferem), como a iteração funciona.
Manter o código ou dado (como mostrado acima com o vetor @websites
) nas visualizações é simples, mas é uma prática ruim e pode trazer problemas com o decorrer do tempo. Para iniciantes vamos mover o vetor @websites
da visão para o controlador. Remove da visão e coloque em app/controllers/welcome_controller.rb
no método index
para parecer assim:
Note que depois de atualizar o navegador nada deverá mudar - isso é por causa das variáveis que começam com @ (chamadas de variáveis de instancia de variáveis) e podem ser acessadas tanto pela visualização quanto pelo controlador.
INSTRUTOR(A): Explique a conexão entre a ação WelcomeController#index
e a visualização; dê ênfase na diferença entre o @ que começa em @websites
e puro url
e nome
.
Crie um modelo
Com os links feitos e escritos na mão, vamos fazer algo com os registros do diário. Dessa vez nós não abusaremos da estrutura do vetor do Ruby, mas com um próprio modelo que represente o dado inserido. Vamos começar gerando o modelo - execute rails generate model Entry title:string date:date contents:text
para criar um modelo Entry
que representará um registro com título, data de publicação e algum conteúdo.
INSTRUTOR(A): Explique o que são modelos e o que é a notação field:type
; explique a diferença entre os tipos string
e text
se necessário.
Migre o banco de dados
Execute rake db:migrate
para migrar o banco de dados para uma tabela com a mesma estrutura dos registros do diário.
INSTRUTOR(A): Explique o que banco de dados são (em termos abstratos, são camadas para armazenar os dados da nossa aplicação e prover as estruturas do modelo) e o porquê são necessárias. Explique que o que estiver na memória não sera persistida por padrão e é preciso explicitamente persistir para que esteja disponível na próxima requisição.
Brinque com o modelo no console do Rails
Agora que temos nosso modelo, podemos começar a criar instancias desse modelo - registros do diário que não estão escritos diretamente na visão HTML. Para isso, vamos aprender uma nova ferramenta: O console do Rails. Comece com rails console
e, uma vez que ele execute e mostre para você >>
, crie alguns registros:
Note como o console - assim como o rails server
- mostra para o você o log do que acontece por trás. Você pode sempre pegar um vetor de todos os registros através de Entry.all
.
INSTRUTOR(A): Explique o que está acontecendo. Devagar.
Visualizando o conteúdo persistido
Adicione a instancia do modelo na visualização existente.
Edite a ação WelcomeController#index
(no arquivo app/controllers/welcome_controller.rb
) e adicione as seguintes linhas antes ou depois das linhas contendo @websites
:
Edite o arquivo app/views/welcome/index.html.erb
e substitua as linhas dos registros do diário com o seguinte:
INSTRUTOR(A): Discuta sobre o que acontece, qual é a ordem dos registros e como podem ser re-ordenados (por exemplo, data inversa) e onde deve acontecer essa lógica
Crie um controlador para os registros do diário
Agora que temos um modelo, precisamos criar um controlador para cuidar das ações relacionadas com as instâncias do modelo (criar novos registros, mostrar, editar e deletar registros existentes). Execute rails generate controller Entries
- isso deve gerar a classe EntriesController
. Verifique rake routes
- e note que apenas o controlador não basta, precisamos ainda apontar as URLs para as ações do controlador.
Edit config/routes.rb
e adicione a linha resources "entries"
em algum lugar dentro do block de Diary::Application.routes.draw
. Execute rake routes
novamente: note que agora sua aplicação terá várias novas rotas.
INSTRUTOR(A): Explique como as rotas do Rails funcionam e como ele fazem para as URLs criadas e mapeadas para as ações do controlador por padrão.
Uma visão de todas os registros
Como pode ser visto na saída de rake routes
, as URLs são ligadas com os suas relativas ações do controlador. Vamos ver o que falta - visite http://localhost:3000/entries no seu navegador. Uh-oh, parece que a ação index
está faltando - vamos adicioná-lo - abra app/controllers/entries_controller.rb
e adicione o método vazio abaixo dentro da definição da classe:
Agora atualize o seu navegador - nós não temos mais um problema unknown action
, temos agora um problema template is missing
. Salve o arquivo sem nenhum conteúdo como app/views/entries/index.html.erb
(note que é igual ao arquivo index.html.erb
da pasta welcome
de antes, mas desta vez será na pasta entries
) e atualize seu navegador novamente - ele deverá agora mostrar uma página vazia. Isso é bom, pois nossa visualização está vazia no momento.
INSTRUTOR(A): Explique como as ações são renderizadas e relacionadas com as visualizações por padrão.
Agora vá para o arquivo app/controllers/welcome_controller.rb
e encontre o método WelcomeController#index
(aquele que começa com def index
). Encontre a linha que atribue a variável @entries
(deve começar com @entries =
) e copie-o para EntriesController#index
(e então para o método index
de EntriesController
, que pode ser encontrado em app/controller/entries_controller.rb
). Similarmente, vá para a visualização app/views/welcome/index.html.erb
e copie o block @entries.each
(todos dentro das linha indentadas inclusive o end
) para app/views/entries/index.html.erb
. Atualize o navegador: ele deverá agora mostrar todos os registros do seu diário.
INSTRUTOR(A): Explique que mesmo isso pareça ter pouco progresso, existe uma mudança significativa: nós não mais estamos operando dentro do contexto da página principal, mas sim de uma lista de registro do diário apenas (sem os links para os outros sites, por exemplo).
Uma visualização de um único registro
Note como, quando você execute rake routes
, a saída diz que o padrão de /entries/:id(.:format)
mapeia para a ação do controlador de entries#show
. Vá para http://localhost:3000/entries/1 - a URL para seu primeiro registro do diário; note como nós, novamente, estamos faltando com a ação em EntriesController
. Adicione a ação, então atualize o navegador e adicione depois também a visualização que está também faltando.
INSTRUTOR(A): Guie na adição da ação que falta e da visualização se necessário; tenha certeza que o processo (desde decifrar descobrir a rota certa em rake routes
) está bem entendido.
Agora, vamos descobrir como interpretar o 1
do fim da URL para mostrar o
registro certo. Crie a ação EntriesController#show
assim:
Esta linha significa ‘pegue o parametro id
e o use para o método Entry.find
para encontrar o registro certo’. Agora edite a visualização app/views/entries/show.html.erb
e coloque o seguinte:
Visite http://localhost:3000/entries/1 e compare com http://localhost:3000/entries/2 para ver que usando params['id']
significa que diferentes registro do diário são mostrados.
INSTRUTOR(A): Explique a parte do :id
de rake routes
é feito para ser uma chave para o hash params
; discuta o que mais pode ter no hash params
.
Ligando registros
Execute rake routes
novamente; note como a linha da ação entries#show
começa com um entry
no prefixo da coluna. Vá para app/views/entries/index.html.erb
e mude a linha responsável para mostrar o título para o abaixo:
Note como utilizamos o método link_to
que tem dois parametros, o texto para ser mostrado (entry.title
) e o caminho do link. Verifique a origem da página para ver o caminho dos títulos seguintes. Note como o caminha é criado pela chamado do método entry_path
com entry
como argumento.
INSTRUTOR(A): Lembre como os links de HTML se parecem. Explique a relação entre entry_path
e o prefixo entry
do rake routes
. Explique como o método entry_path
precisa do argumento entry
. Explique o que o método entry_url
faz (e como ele difere do método entry_path
) se você quiser.
Agora vamos voltar para a página indice com todos os registros: edit app/views/entries/show.html.erb
e adicione o link para os registros do indice, assim:
Note, novamente, como o prefixo entries
de rake routes
é utilizado para construir o nome pelo método entries_path
. Note como o método não precisa de parametro.
Criando registros pela IU
Adicionando o formulário novo registro
Agora que nós temos um modo de mostrar a lista com todos os registros e mostrar apenas um registro, vamos adicionar um modo de criar novos registros do diário. Execute rake routes
e tente descobrir qual URL (e ação) é responsável pela criação do novo registro.
Vá para o indice de todos os registros e adicione o link para criar um novo registro:
Clique no link - e adicione a ação que falta e a visualização.
INSTRUTOR(A): Garanta que este processo é bem entendido até aqui.
Edite a visualização app/views/entries/new.html.erb
e cole o abaixo:
Nota: podemos pular os labels por agora
INSTRUTOR(A): Mostre como o HTML é produzido pelo helper form_for
e tente explicar como ele funciona.
Manipulando o formulário de ‘novo registro’
Atualize o navegador e tente adicionar um novo registro - você deverá o conhecido erro unknow action
. Adicione a ação em EntriesController
, mas para iniciantes vamos mostrar o que a ação recebe:
Atualize o navegador e inspecione o que exatamente a ação recebe de params.
INSTRUTOR(A): Explique como preencher um campo de texto e uma area de texto e submeter o formulário acaba com todos os params sendo enviados (post
) para a ação do controlador. Explique o que .inspect faz.
Criando e persistindo um novo registro
Edite a ação create
e faça parecer assim:
Note como tentamos pegar os parametros do novo registro(seu título e conteúdo) do hash params
e então criamos um novo registro a partir dele, assim como no console. Tente submeter o formulário novamente - note como ainda não conseguimos, pois recebemos ActiveModel::ForbiddenAttributesError
.
- Nota: podemos pular a parte de strong_parameters no começo, mantendo a aplicação insegura de injeções de parametros
- config.action_controller.permit_all_parameters = true
- ^^ sim, mas será removido em breve.
- talvez não antes dos workshops ;)
Esse erro é por causa de ações de segurança - é relativamente simples de fazer um POST com quaisquer parametros que o usuário quer, e Rails nos protege de um usuário desonesto que quer setar parametros que ele não deveria setar (como id
). Precisamos declarar quais parametros o usuário consegue mudar; mude a primeira linha de create
para:
Agora tente submeter o formulário novamente - deste vez deverá funcionar e você deverá ser redirecionado para um novo registro recém-criado.
INSTRUTOR(A): Tenha certeza que a parte dos parametros do novo registro está bem claro e que os campos aceitos devem ser permitidos explicitamente.
Editando pela IU
Adicionando um formulário de edição de registro
Agora que podemos visualizar os registros criados, vamos também adicionar uma opção para editá-los. Execute rake routes
e tente adivinhar qual rota é responsável pela edição do registro.
INSTRUTOR(A): Garanta que tudo está claro até aqui.
Edite a visualização app/views/entries/show.html.erb
e adicione a linha abaixo em algum lugar:
Atualize a visualização do registro e clique no link. Adicione a ação que falta e a visualização também.
INSTRUTOR(A): Novamente, tenha certeza que tudo está claro.
Vamos primeiro garantir que nossa ação edit
expõe o registro certo para a visualização. Garanta que a ação edit
pareça igual a ação show
- isto é, pegue o registro baseado no id que vem da URL:
Agora copie o conteúdo da visualização app/views/entries/new.html.erb
para app/views/entries/edit.html.erb
, mas mude a primeira linha para que o formulário deste registro em particular - e opcionalmente, adicione um link para voltar na visualização do registro:
INSTRUTOR(A): Garanta que isto esteja claro.
Agora tente submeter o formulário - que ação está faltando? Cria no controlador:
Verifique se tudo isso funciona e se você pode editar os registros.
INSTRUTOR(A): Garanta que a ação update
e seu conteúdo estejam claros e foram entedidos - desde permitir os parametros através dos registros até redirecionar para o caminho certo.
Ideias para o futuro
Brinque com sua aplicação! Aqui estão algumas ideias que você queira adicionar:
- extraia o formulário para uma partial
- links para editar o registro diretamente do indice de registros,
- um jeito de deletar um registro,
- um jeito de editar as datas dos registros,
- um modelo para acompanhar as URLs e os nomes (a lista na página principal),
- atribuir uma data de entrada para o futuro e não mostar esses registros no indice até que o dia chegue,
- embutir automaticamente URL de videos,
- suporte para diferente autores,
- suporte para diferente categorias de registros,
- upload e visualização de imagens.
Outros Guias
- Handy cheatsheet for Ruby, Rails, console etc.
- Guia 1: Tutorial de Instalação para Rails Girls
- Guia 2: Tutorial para criação da app Rails Girls
- Guia 3: Como enviar para o GitHub
- Guia 4: Colocando seu app online em…
- Guia 5: Funcionalidades de uma área de comentários para a app Rails Girls
- Guia 6: Adicione design à sua aplicação com HTML e CSS
- Guia 7: Thumbnails em listas de ideas
- Guia 8: Autenticação (para usuários) com Devise
- Guia 9: Adicionando Gravatar para a aplicação
- Guia 10: Melhorando seu design da sua aplicação com HTML e CSS
- Guia 11: Continuous Deployment
- Guia 12: Construindo um aplicativo de votação em Sinatra
- Guia 13: Construa um diário em Ruby on Rails (Você está aqui!)
- Guia 14: Adicione back-end ao seu aplicativo (páginas de administração)
- Guia 15: Acesse explicações adicionais do app Rails Girls