ruby-on-rails 在rails中,Turbo只是将来自服务器的响应附加到当前页面的末尾

ykejflvf  于 2023-03-09  发布在  Ruby
关注(0)|答案(1)|浏览(123)

问题是:Turbo只是将服务器的响应附加到当前页面的末尾。没有像预期的那样替换页面。
最近从Rails6升级到了7。我也从importmap切换到了esbuild。
我有一个窗体正在向create方法发送一个post,控制器的响应是

if @stamp.save       
        redirect_to stamps_path, notice: "Input saved"
      else

奇怪的是,响应被从顶部附加到源代码的底部,所以在原始源代码的末尾,一个来自响应的新的头部分被附加为

<...> The whole initial html <...>
</body>
<title>Page title</title> <-- The server response gets appended after </body>
<meta .... the whole page gets repeated again

不知道该给你看什么,我一直在挖掘所有的设置等。我从来没有见过涡轮增压这样的行为与响应。
一个二个一个一个
我一直在尝试复制另一个我使用Turbo的rails应用程序。我一直在查看所有设置等。其他页面可以接受redirect_to并按预期替换内容。我使用haml,所以HTML结构应该没问题。

k3fezbri

k3fezbri1#

我只能想到一种可能:您有show.erb模板。只需将其重命名为show.html.erb(或 .haml.slim,无所谓)。
默认情况下,表单以 TURBO_STREAM 的形式提交,这是 rails 在日志中显示的内容,但这并不是全部。表单提交请求设置Accept头:

Accept: text/vnd.turbo-stream.html, text/html, application/xhtml+xml
#       ^
# here is where `TURBO_STREAM` comes from

这些是 turbo 期望接收的响应Content-Type。当您在控制器操作中使用respond_to块时,Accept标头决定要调用哪个format块:

respond_to do |format|
  if @model.save(model_params)
    # if you have turbo_stream, it will run first
    # format.turbo_stream { render turbo_stream: turbo_stream.replace(model) }
    # if you don't have turbo_stream, next format in `Accept` header is html
    format.html { redirect_to model_url(@model) }
    format.json { render :show, status: :ok, location: @model }
    # if nothing matches, you get `ActionController::UnknownFormat` error.
    # the one you get when trying to render `format.js`, but Turbo 
    # doesn't handle js format, so it doesn't send `Accept: text/javascript`
  else
    format.html { render :edit, status: :unprocessable_entity }
    format.json { render json: @model.errors, status: :unprocessable_entity }
  end
end

当你使用respond_to块时,rails 会自动设置一些渲染选项,其中一个是:content_type,它反过来设置Content-Type响应头。因此,如果format.html块运行,它设置Content-Type: text/htmlturbo 知道如何通过重定向或替换页面内容来处理。
重要的是我们从 turbo_stream 格式转换为 html 格式。不用说,html 需要呈现html外观的响应,turbo_stream 必须是<turbo-stream>标记。
当你不使用respond_to块时会发生什么。Rails 会尝试渲染一个与格式匹配的模板。例如,turbo_stream 请求会先查找show.turbo_stream.erb,然后查找show.html.erb,最后查找show.erb,如下所示:

render :show, formats: [:turbo_stream, :html]

假设它找到了show.html.erb,因为存在html扩展,rails 会将response Content-Type 设置为text/html,一切都按预期运行。
但是,如果它找到show.erb,没有任何东西可以告诉 rails 它是 html 格式,我们没有使用respond_to块,因此响应 Content-Type 没有显式设置,剩下的唯一选项是回退到第一个 Accept 类型,即 turbo_stream。现在您正在呈现一个 html 模板,但响应类型是 turbo_stream,并且不存在<turbo-stream>标签。
turbo 看到一个 turbo_stream 响应时,它会将其附加到文档中,这就是您所看到的。由于没有 指令,它就保持不变。
长话短说,一路沿着的一些东西需要设置正确的内容类型。
可以使用respond_to块来设置必要的渲染选项,也可以自己设置渲染选项:或者通过使用html.erbturbo_stream.erb扩展让 rails 知道内容类型。
注意,当您重定向时,turbo_stream 内容类型将保留,因为 turbo 在前端处理重定向。如果show操作中没有html.erb扩展和respond_to块,则会出现内容类型不匹配。

相关问题