-
Notifications
You must be signed in to change notification settings - Fork 330
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce
turbo-stream[action=visit]
and `#break_out_of_turbo_frame…
…_and_redirect_to` Introduces the `Turbo::Stream::Redirect` concern to introduce the `#break_out_of_turbo_frame_and_redirect_to` and `#turbo_stream_redirect_to` methods. The `#break_out_of_turbo_frame_and_redirect_to` draws inspiration from the methods provided by the [Turbo::Native::Navigation][] concern. When handling requests made from outside a `<turbo-frame>` elements (without the `Turbo-Frame` HTTP header), respond with a typical HTML redirect response. When handling request made from inside a `<turbo-frame>` element (with the `Turbo-Frame` HTTP header), render a `<turbo-stream action="visit">` element with the redirect's pathname or URL encoded into the `[location]` attribute. When Turbo Drive receives the response, it will call `Turbo.visit()` with the value read from the `[location]` attribute. ```ruby class ArticlesController < ApplicationController def show @Article = Article.find(params[:id]) end def create @Article = Article.new(article_params) if @article.save break_out_of_turbo_frame_and_redirect_to @Article else render :new, status: :unprocessable_entity end end end ``` Response options (like `:notice`, `:alert`, `:status`, etc.) are forwarded to the underlying redirection mechanism (`#redirect_to` for `Mime[:html]` requests and `#turbo_stream_redirect_to` for `Mime[:turbo_stream]` requests). This enables server-side actions to navigate the entire page with a, regardless of the provenance of the request. Typically, an HTTP that would result in a redirect nets two requests: the first submission, then the subsequent GET request to follow the redirect. In the case of a "break out", the same number of requests are made: the first submission, then the subsequent GET made by the `Turbo.visit` call. To support this behavior, this commit introduces the first `@hotwire/turbo-rails`-specific Turbo `StreamAction`: the `turbo-stream[action="visit"]`. [Turbo::Native::Navigation]: https://github.com/hotwired/turbo-rails/blob/v2.0.11/app/controllers/turbo/native/navigation.rb
- Loading branch information
1 parent
aee95a8
commit dea6972
Showing
14 changed files
with
199 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,78 @@ | ||
module Turbo::Streams::Redirect | ||
extend ActiveSupport::Concern | ||
|
||
def redirect_to(options = {}, response_options = {}) | ||
turbo_frame = response_options.delete(:turbo_frame) | ||
turbo_action = response_options.delete(:turbo_action) | ||
location = url_for(options) | ||
private | ||
|
||
if request.format.turbo_stream? && turbo_frame.present? | ||
alert, notice, flash_override = response_options.values_at(:alert, :notice, :flash) | ||
flash.merge!(flash_override || {alert: alert, notice: notice}) | ||
# Instruct Turbo Drive to redirect the page, regardless of whether or not the | ||
# request was made from within a `<turbo-frame>` element. | ||
# | ||
# When handling requests made from outside a `<turbo-frame>` elements (without | ||
# the `Turbo-Frame` HTTP header), respond with a typical HTML redirect | ||
# response. | ||
# | ||
# When handling request made from inside a `<turbo-frame>` element (with the | ||
# `Turbo-Frame` HTTP header), render a `<turbo-stream action="visit">` element | ||
# with the redirect's pathname or URL encoded into the `[location]` attribute. | ||
# | ||
# When Turbo Drive receives the response, it will call `Turbo.visit()` with | ||
# the value read from the `[location]` attribute. | ||
# | ||
# class ArticlesController < ApplicationController | ||
# def show | ||
# @article = Article.find(params[:id]) | ||
# end | ||
# | ||
# def create | ||
# @article = Article.new(article_params) | ||
# | ||
# if @article.save | ||
# break_out_of_turbo_frame_and_redirect_to @article | ||
# else | ||
# render :new, status: :unprocessable_entity | ||
# end | ||
# end | ||
# end | ||
# | ||
# Response options (like `:notice`, `:alert`, `:status`, etc.) are forwarded | ||
# to the underlying redirection mechanism (`#redirect_to` for `Mime[:html]` | ||
# requests and `#turbo_stream_redirect_to` for `Mime[:turbo_stream]` | ||
# requests). | ||
def break_out_of_turbo_frame_and_redirect_to(options = {}, response_options_and_flash = {}) # :doc: | ||
respond_to do |format| | ||
format.html { redirect_to(options, response_options_and_flash) } | ||
|
||
case Rack::Utils.status_code(response_options.fetch(:status, :created)) | ||
when 300..399 then response_options[:status] = :created | ||
if turbo_frame_request? | ||
format.turbo_stream { turbo_stream_redirect_to(options, response_options_and_flash) } | ||
end | ||
end | ||
end | ||
|
||
render "turbo/streams/redirect", **response_options.with_defaults( | ||
locals: {location: location, turbo_frame: turbo_frame, turbo_action: turbo_action}, | ||
location: location, | ||
) | ||
else | ||
super | ||
# Respond with a `<turbo-stream action="visit">` with the `[location]` | ||
# attribute set to the pathname or URL. Preserves `:alert`, `:notice`, and | ||
# `:flash` options. | ||
# | ||
# When passed a `:status` HTTP status code option between `300` and `399`, | ||
# replace it with a `201 Created` status and set the `Location` HTTP header to | ||
# the pathname or URL. | ||
def turbo_stream_redirect_to(options = {}, response_options_and_flash = {}) # :doc: | ||
location = url_for(options) | ||
|
||
self.class._flash_types.each do |flash_type| | ||
if (type = response_options_and_flash.delete(flash_type)) | ||
flash[flash_type] = type | ||
end | ||
end | ||
|
||
if (other_flashes = response_options_and_flash.delete(:flash)) | ||
flash.update(other_flashes) | ||
end | ||
|
||
case Rack::Utils.status_code(response_options_and_flash.fetch(:status, :created)) | ||
when 201, 300..399 | ||
response_options_and_flash[:status] = :created | ||
response_options_and_flash[:location] = location | ||
end | ||
|
||
render turbo_stream: turbo_stream.visit(location), **response_options_and_flash | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.