free software, web technologies and heavy metal coding (and ruby of course)

Rails 5, Turbolinks 5 and form errors

I was one of those Rails developers that avoided Turbolinks at all costs. I even removed it from a lot of existing applications. The new Turbolinks with Rails 5 though was said to be a lot better (I read some blog post about it, but I don't remember which one exactly). I gave it another spin in my latest project.

It all went pretty well, but then I noticed that for forms it actually was not working as expected, as reflected in issue 85:

When you submit a form that has errors, Rails normally renders the new action again with the form and the errors. With Turbolinks as it is setup right now, the redirects are handled nicely, but this piece requires you to build your own create.js.erb response to render the errors.

So Turbolinks does not automatically render form errors. I was not keen at all to handle something Rails takes care of so nicely by myself. After trying out the various solutions in the above mentioned issue I was going for a modified version of minimul's solution.

def render_with_turbolinks(*options, &block)
  html = render_to_string(*options, &block)

  script = <<-SCRIPT
      var doc = document.implementation.createHTMLDocument('response');
      doc.documentElement.innerHTML = "#{ActionController::Base.helpers.j(html)}";
      document.documentElement.replaceChild(doc.body, document.body);
      window.scroll(0, 0);

  self.status = 200
  self.response_body = script
  response.content_type = 'text/javascript'

I preferred that solution over the other suggested ones as it is the least intrusive.

The one thing I modified was using document.implementation.createDocument instead of DOMParser, as this feature is not supported in PhantomJS (See HTML to DOM for more information on this).

With this addtition Turbolinks 5 worked out very well for my newest project. The application feels snappy like an SPA, while we were able to use the still very comfortable Rails stack.