05. Errei! Como corrigir ou apagar?
Deixe os erros acontecerem. Como no capítulo 04, os erros deste capítulo aparecem de propósito, seguindo o caminho da requisição a partir do link Editar (veja “O caminho dos erros”, abaixo). Não corrija antes, não diga “é só um erro, ignora” e não adiante a solução. Quem prevê o erro do update antes de ele aparecer está mostrando que entendeu o caminho, e vale comemorar.
E o formulário repetido é de propósito. O edit.html.erb é uma cópia do new.html.erb, com outro título e outro botão, e a gente não usa partial agora. Escrever o formulário duas vezes mostra à participante o que muda (o recado que já existe manda o formulário para o update) e o que não muda, e a repetição reforça o que ela acabou de aprender. A partial vem depois, como “Para ir além”, no passo 9 do capítulo 07, e quem sentir falta dela antes pode ver a resposta no “O que aconteceu?” deste capítulo. Veja também “O formulário copiado”, em “Confusões comuns”.
Perguntas para o “Pense antes”
- “Se duas pessoas escreverem ‘Oi!’, como o app sabe qual das duas apagar?” Leva ao
id. - “Você já apagou alguma coisa sem querer? O que teria ajudado?” Leva à confirmação.
- “Corrigir é parecido com postar? O que muda?” Leva à ideia de formulário preenchido e às duas ações,
editeupdate, que fazem par com onewe ocreatedo capítulo 04.
O caminho dos erros
Como no capítulo 04, os erros aparecem de propósito e seguem o caminho da requisição, começando pelo link:
- O link
link_to "Editar", edit_message_path(message)sem a rota: NoMethodError,undefined method 'edit_message_path'. Falta a rota. Como nonew_message_path, quem quebra é a página principal inteira. - Com
:editnoonly, clicar em Editar: Unknown action,The action 'edit' could not be found. Falta a ação. - Com a ação: No view template for interactive request. Falta a view.
- Com o
edit.html.erb: NoMethodError in Messages#edit,undefined method 'message_path'. Oform_withde um recado que já existe aponta para/messages/3(oupdate), e essa rota ainda não existe. Falta a rota doupdate. - Clicar em Salvar: nada acontece na tela. No terminal do servidor, aparece
The action 'update' could not be found. Como no capítulo 04, erros de formulário só aparecem no terminal.
No passo 4, a participante vê o número do recado no endereço (/messages/3/edit) e liga ele ao id do capítulo 02. No passo 8, ela é convidada a prever o erro do update antes de ver. Se a pessoa acertar, vale comemorar: é o sinal de que entendeu o caminho. No passo 9 (apagar), rota, ação e botão entram de uma vez.
Confusões comuns
- O número do recado. Cada pessoa vai ter um
iddiferente. Se aparecerCouldn't find Message, o número no endereço não existe: use o link Editar. - Onde colocar as ações. As ações novas ficam antes do
private. Depois dele, o Rails não encontra a ação, e o erro é o mesmo de quando ela não existe. - O
@. Oedite oupdateusam@message; odestroyusamessage, sem@. A diferença está explicada no “O que aconteceu?”. - A confirmação não aparece. Normalmente é a sintaxe das chaves em
form: { data: { turbo_confirm: "..." } }, ou a página guardada no navegador (Cmd+Shift+R). - O formulário copiado. O
edit.html.erbé uma cópia donew.html.erb, com outro título e outro botão. Alguém pode perguntar se dá para não repetir o formulário. Dá, com uma partial, mas a gente deixou de fora de propósito. Se houver tempo e curiosidade, é um bom desafio.
REST, verbos HTTP e códigos de status
Contexto só para a mentoria. Não precisa levar isso para as participantes: o guia mostra os verbos na prática (a tabela do “O que aconteceu?” deste capítulo), sem usar a palavra REST. Se alguém se interessar, é um ótimo assunto para depois do workshop.
O que é REST. É um jeito de organizar um app web (ou uma API) em torno de recursos, como “recados”, em que cada operação é a combinação de um endereço com um verbo HTTP. O resources :messages é o REST do Rails: ele cria as sete rotas padrão, e o only escolhe quais. O Mural de recados usa seis delas (todas menos o show).
Outros nomes que você vai ouvir.
- REST vem de Representational State Transfer (“transferência de estado representacional”), e foi descrito por Roy Fielding na tese de doutorado dele, em 2000 (capítulo 5 da tese, em inglês).
- RESTful é o adjetivo: um app, uma rota ou uma API “RESTful” é uma que segue o REST. O guia de rotas do Rails usa essa palavra (“RESTful routes”).
- API REST, REST API ou RESTful API (nas empresas, em geral só “API”) é uma API que usa esse estilo: as mesmas rotas e os mesmos verbos, mas respondendo com dados, em geral em JSON, e não com páginas HTML.
- Resourceful routing, ou resource routing, é como o Rails chama o
resourcesna documentação (“Resource Routing: the Rails Default”): declarar de uma vez as rotas de um recurso. - CRUD (Create, Read, Update, Delete: criar, ler, atualizar e apagar) é o nome das quatro operações básicas sobre os dados. Muita gente usa “CRUD” e “REST” como sinônimos, mas o CRUD fala do que se faz com os dados, e o REST, de como organizar os endereços e os verbos. As seis ações do Mural de recados cobrem o CRUD inteiro:
createenew(criar),index(ler),editeupdate(atualizar) edestroy(apagar).
Uma ressalva que costuma aparecer em conversas de quem já programa: na prática, quase toda “API REST” segue só uma parte das ideias do Fielding. O rigor completo do REST inclui, por exemplo, links dentro das respostas que dizem o que dá para fazer a seguir (o HATEOAS), e quase ninguém usa. Por isso, “REST” no dia a dia costuma querer dizer só “recursos com endereços e verbos, como o resources do Rails”.
| Verbo | Endereço | Ação | Para quê |
|---|---|---|---|
GET |
/messages |
index |
ver a lista |
GET |
/messages/new |
new |
abrir o formulário de recado novo |
POST |
/messages |
create |
criar |
GET |
/messages/3/edit |
edit |
abrir o formulário de correção |
PATCH |
/messages/3 |
update |
atualizar |
DELETE |
/messages/3 |
destroy |
apagar |
Por que os verbos importam.
- O endereço diz o quê, o verbo diz o que fazer.
/messages/3serve para atualizar (PATCH) e para apagar (DELETE). Sem o verbo, a rota não saberia qual ação chamar. GETnão muda nada. É a regra mais importante: umGETsó lê. Navegadores, buscadores e ferramentas que “pré-carregam” links fazemGETà vontade. Se apagar um recado fosse umGET, um robô passando pelo site apagaria tudo. Por isso o Apagar é um botão (button_to), e não um link.- Formulários HTML só sabem
GETePOST. O Rails simula oPATCHe oDELETEcom um campo escondido,_method, que oform_withe obutton_tocolocam sozinhos. No terminal do servidor, aparece o verbo final (PATCH,DELETE).
Os códigos de status. Toda resposta leva um número que diz como foi a requisição. Os que aparecem no projeto, no terminal do servidor (na linha Completed …):
| Código | Nome | Onde aparece |
|---|---|---|
200 |
OK | qualquer página que abriu certinho |
302 |
Found (redirecionamento) | depois do create, do update e do destroy, com o redirect_to |
404 |
Not Found | rota que não existe, ou ação que não existe |
422 |
Unprocessable Content | recado recusado pelas validações, no capítulo 07 |
500 |
Internal Server Error | erro no código do app, como um NoMethodError |
- O
422do capítulo 07 é o que faz o Turbo mostrar a página. Depois de enviar um formulário, o Turbo só troca a tela se a resposta for um redirecionamento ou um erro (4xxou5xx). Comrender :newe status200, nada aparece, e o console do navegador avisa “Form responses must redirect to another location”. Daí ostatus: :unprocessable_entity. - O nome mudou. O guia usa
:unprocessable_entity, que é o nome que a maioria dos exemplos na internet usa. No Rails 8.1, o nome oficial passou a ser:unprocessable_content, e o terminal mostra422 Unprocessable Content. Os dois funcionam, sem aviso. - Os erros de formulário do capítulo 04 também não aparecem na tela. Eles são
404(falta a rota ou a ação docreate) e422(a proteção de formulários, no Codespaces). Por que eles não aparecem, se o422do capítulo 07 aparece? A página de erro do Rails tem a linha<meta name="turbo-visit-control" content="reload">, que pede ao Turbo para recarregar a página em vez de mostrar a resposta. O navegador recarrega a página Novo recado, e o erro só fica no terminal. A página do422é uma view do próprio app, sem essa linha, e por isso aparece. - Para saber mais sobre o Turbo (em inglês), na documentação oficial do Turbo Drive: Redirecting After a Form Submission (o que o Turbo espera como resposta a um formulário: um redirecionamento ou um erro
4xxou5xx) e Ensuring Specific Pages Trigger a Full Reload (oturbo-visit-control). A explicação geral do Turbo está no Turbo Handbook. O capítulo 04 também fala disso, em “Erros de formulário só aparecem no terminal”.
Para quem quiser ir além depois do workshop: uma API REST usa as mesmas rotas e os mesmos verbos, mas responde com dados (geralmente JSON) em vez de páginas HTML. É um bom próximo passo, junto com o guia oficial Rails Routing from the Outside In, em inglês.
Por que não usamos status: :see_other
Contexto só para a mentoria. Não precisa levar para as participantes: o capítulo não fala do :see_other nem do status 303. Use só se alguém comparar com o código de um scaffold ou de outro tutorial.
O scaffold do Rails usa redirect_to ..., status: :see_other no destroy. Ele é necessário quando a requisição sai do navegador como DELETE de verdade, por exemplo num link com data-turbo-method="delete". O button_to manda um POST com _method=delete, e o redirecionamento comum funciona. Por isso, o guia deixa o status de fora. Se a pessoa trocar o botão por um link, ele passa a ser necessário.