3

我有一个控制器操作,我想接收表单数据,执行一些业务逻辑,然后刷新表单。如果我将对象保存在数据库中然后使用redirect_to,这可以正常工作。我希望控制器在内存中编辑对象并直接呈现响应。

例如,采用标准 rails 5.1.4 生成的应用程序,如下所示:

rails new turbolinks_example
rails g scaffold Thing name
rails db:migrate

为简洁起见并启用 turbolinks 的形式稍作编辑:

<%= form_with(model: thing) do |form| %>
  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name, id: :thing_name %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

A) 现在我们编辑控制器以更改对象。这使用重定向进行编辑和工作:

ThingsController < ApplicationController
...
  def update
    if @thing.update(thing_params)
      @thing.update name: "#{@thing.name} is OK"
      redirect_to edit_thing_path(@thing)
    end
  end 

B)这使用渲染并且不起作用:

class ThingsController < ApplicationController
  ...
  def update
      if @thing.update(thing_params)
        @thing.name = "#{@thing.name} is OK"
        render :edit
      end
  end
end

使用 A) - 控制器接收更新请求 - 修改对象(并保存) - 返回重定向 - 呈现重定向的 url - 更新 DOM 使用 B) - 控制器接收更新请求 - 修改对象(在内存中) -响应被渲染 - 浏览器接收到响应,但被忽略

收到的回复,看起来是正确的。完整的 HTML,包含对对象所做的更改。如何让 turbolinks 注意到它并像往常一样替换 document.body?

完整的项目,包括 development.log在 Github

4

1 回答 1

3

问题在于,在 Rails 5 中:

  • 默认情况下,表单是远程的:它们通过 AJAX 发送,除非local: true提供
  • 当呈现 HTML 作为对 AJAX 调用的响应时,什么都不会发生,当然,除非客户端中有自定义 javascript 处理响应
  • Turbolinks 默认是开启的,可以redirect_to正常处理,但是什么都不做render

我认为这是 Rails 中的一个不一致之处,会导致很多混乱,例如您在代码中暴露的问题。我创建了一个gemturbolinks_render来解决这个问题。我也写了一篇关于这个问题的小帖子

我希望,以一种或另一种方式,这在未来的 Rails 版本中得到修复。

于 2018-06-21T11:03:14.610 回答