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
The problem is that, in Rails 5:
local: true
providedredirect_to
properly, but does nothing forrender
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.