Aprenda / Ruby on Rails

FundamentosAula 5 de 2016 min0% da trilha

Controllers e rotas REST

resources gera 7 rotas de uma vez — entender as 7 evita reinventar rota fora do padrão REST.

resources :produtos em routes.rb gera 7 rotas de uma vez, cada uma mapeada pra uma action do controller. Saber essas 7 de cor evita inventar rota fora do padrão REST — o que quase sempre é sinal de que falta uma action, não de que o REST não serve pro caso.

as 7 rotas REST
Verbo    URL                Action    Uso
GET      /produtos          index     listar todos
GET      /produtos/new      new       (só em app c/ view — API não usa)
POST     /produtos          create    criar um novo
GET      /produtos/:id      show      mostrar um específico
GET      /produtos/:id/edit edit      (só em app c/ view — API não usa)
PATCH    /produtos/:id      update    atualizar parcialmente
DELETE   /produtos/:id      destroy   remover

Numa API, new/edit não fazem sentido (não existe formulário HTML pra "editar") — por isso o gerador com --api já não inclui essas duas.

O controller — uma action por rota

app/controllers/produtos_controller.rb
class ProdutosController < ApplicationController
  before_action :set_produto, only: [:show, :update, :destroy]

  def index
    render json: Produto.all
  end

  def show
    render json: @produto
  end

  def create
    produto = Produto.new(produto_params)
    if produto.save
      render json: produto, status: :created
    else
      render json: { errors: produto.errors.full_messages }, status: :unprocessable_entity
    end
  end

  def update
    if @produto.update(produto_params)
      render json: @produto
    else
      render json: { errors: @produto.errors.full_messages }, status: :unprocessable_entity
    end
  end

  def destroy
    @produto.destroy
    head :no_content
  end

  private

  def set_produto
    @produto = Produto.find(params[:id])
  end

  def produto_params
    params.require(:produto).permit(:nome, :preco)
  end
end

before_action :set_produto, only: [...] evita repetir Produto.find(params[:id]) em 3 actions — roda antes delas, deixando @produto pronto. E cada branch de erro devolve um status HTTP correto (422 pra validação falhando, 204 pra delete sem corpo) — o código de status é parte do contrato da API, não detalhe.

Exercício

Se Produto.find(params[:id]) não achar o registro, o Rails levanta ActiveRecord::RecordNotFound. Sem tratamento nenhum, isso vira erro 500. Que status HTTP deveria ser esse, e onde você trataria isso pra não repetir em cada controller?

Quiz rápido

Por que new/edit não aparecem num controller gerado com --api?
Pra que serve before_action :set_produto, only: [:show, :update, :destroy]?