How do I render a reply into turbolinks 5 with rails 5

977 views Asked by At

I have a controller action where I'd like to receive form data, execute some business logic, then refresh the form. This works Ok if I save the object in the database then use a redirect_to. I would prefer the controller edit the object in memory and render the response directly.

For example, take a standard rails 5.1.4 generated app generated like so:

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

The form, slightly edited for brevity and to enable 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) Now we edit the controller to change the object. This uses a redirect to edit and works:

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) This uses a render and does not work:

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

With A) - Update request is received by controller - Object is modified (& saved) - Redirect is returned - Rediredted url is rendered - DOM is updated With B) - Update request is received by controller - Object is modified (in memory) - Response is rendered - Response is received by browser, but ignored

The response received, looks correct. Full HTML, with the changes made to the object. How do I get turbolinks to notice it and replace document.body like normal?

The full project, including development.log is on Github

1

There are 1 answers

3
jmanrubia On

The problem is that, in Rails 5:

  • Forms are remote by default: they are sent via AJAX unless local: true provided
  • When rendering HTML as a response to an AJAX call, nothing happens unless, of course, there is custom javascript in the client handling the response
  • Turbolinks is enabled by default, which handles redirect_to properly, but does nothing for render

I think this is an inconsistency in Rails that causes much confusion, such as the problem you exposed with your code. I created a gem turbolinks_render to deal with this problem. I also wrote a little post on this very same problem.

I hope that, one way or other, this gets fixed in future Rails versions.