O mesmo respond_to, um segundo formato

Prévia grátis 3 min de leitura

Todo broadcast do curso anterior disparou sem requisição nenhuma: um envio do servidor, sem ninguém pedir. O turbo stream deste curso responde a uma pergunta. O envio de um formulário comum, por HTTP comum, recebe a resposta do format.turbo_stream, um ramo do mesmo bloco respond_to que o Rails sempre usou para format.html e format.json.

O menor exemplo desta aplicação

app/controllers/locales_controller.rb, inteiro, sem edição:

class LocalesController < ApplicationController
  def update
    locale = params[:locale]
    if I18n.available_locales.include?(locale.to_sym)
      I18n.locale = locale.to_sym
      session[:locale] = locale
    end

    respond_to do |format|
      format.turbo_stream
      format.html { redirect_back fallback_location: root_path }
    end
  end
end

Trocar o idioma do site é uma requisição PATCH para essa action. format.turbo_stream sem bloco quer dizer o mesmo que format.html queria no exemplo messages#create da documentação, visto no curso anterior: renderizar o template correspondente por convenção, aqui app/views/locales/update.turbo_stream.erb, e devolvê-lo com o content type certo.

O que decide qual ramo roda

A requisição do cliente traz um header Accept, e o respond_to escolhe o bloco de formato que bate com ele. Quando o Turbo envia um formulário com qualquer método que não seja GET, ele coloca text/vnd.turbo-stream.html na frente do text/html de sempre nesse header. Só que o seletor de idioma não é um formulário. Um controller Stimulus, o ui--locale-switch, manda o PATCH ele mesmo com fetch. Ele pede só text/vnd.turbo-stream.html e entrega a resposta ao Turbo.renderStreamMessage. Nos dois casos o cliente diz que entende streams, e o format.turbo_stream responde. Um cliente que nunca diz isso, como o curl, cai no format.html: o mesmo redirect_back que qualquer app Rails de antes do Hotwire rodaria.

Uma action, dois formatos de resposta

Nada na lógica do próprio LocalesController#update se importa com o ramo. Ler params[:locale], conferir se é válido e gravar a sessão acontecem uma vez, acima do bloco respond_to, igual para os dois. Só a resposta se divide: um template .turbo_stream.erb para um cliente, um redirect para o outro. O exemplo de format.turbo_stream do curso anterior mostrou a mesma ideia ao lado de format.json e format.html. O Rails escolher um template pelo formato que o cliente pede não é coisa do Hotwire. format.turbo_stream é só mais um ramo numa maquinaria que o Rails sempre teve.

Pontos-chave

  • format.turbo_stream dentro de um respond_to é um mecanismo de requisição e resposta, e não um broadcast. Ele responde à requisição que o disparou, como format.html e format.json sempre fizeram.
  • O LocalesController#update desta aplicação junta um format.turbo_stream sem bloco (renderiza locales/update.turbo_stream.erb por convenção) com format.html { redirect_back ... }.
  • O header Accept do cliente escolhe o ramo. Os envios de formulário do Turbo que não são GET e o seletor de idioma desta aplicação (um fetch no Stimulus) pedem text/vnd.turbo-stream.html. Um cliente que nunca pede isso cai no format.html.
  • A lógica do controller (validar e aplicar o idioma) roda uma vez, do mesmo jeito, antes de o ramo ser escolhido. Só o formato da resposta muda entre os dois.
Aula 1 de 7 · grátis

Continue com a aula 2

Múltiplas ações, uma resposta

Um único POST de comentário devolve cinco ações de stream com alvo, rodadas no mesmo quadro de animação.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...