Problems Integrating Hotwire Into Existing Rails Project

Hello everyone. I just joined this community and this is my first post.

I’ve been following several Hotwire tutorials and have built some prototypes with the technology. I’ve been impressed with how easy it is to get SPA-like responsiveness with much less complexity compared to JS front end frameworks.

However, I’ve found that when I try to translate the code and process from my prototypes to my existing Rails project it simply never works. What’s worse is that I don’t know why.

I’ve tried to write some tracer code with the following general process:

  1. Include the Hotwire gem
  2. Install Hotwire via terminal command
  3. Include broadcasts from the relevant model
  4. Apply a turbo_stream_from tag as a listener at the view level
  5. Include a turbo_frame_tag where you want the model data to be updated

This works reliably in my prototypes, but won’t work in my existing project. I’m suspecting it may be because my existing project isn’t using the latest version of Rails nor Ruby? (Upgrading has not proved easy either.) I am currently using Ruby version 2.7.1 and Rails version 6.0.2.

I know I should be offering up some of my project code, but I don’t even know where to begin. If anyone would be able to offer me some guidance I’d REALLY appreciate it. Thank you!

If it helps at all these are the kinds of terminal messages I’m getting when attempting to get Hotwire to autoupdate a list of model instances on an index page. It seems like the broadcast is working but my listener isn’t?

You might have more luck asking in the Hotwire forum?

I’m in the process of integrating in our app, so far Stimulus is hooked up. Next on the list is Turbo, so I can’t comment on that.

Can you see any errors in your browser console or network tab?

Might be this other project is using webpack and the other one used asset pipeline?

Thank you! I’ve made a post over on that forum.

There are no errors popping up on the Chrome dev tools. It seems as though the broadcast from the model is working correctly. It also seems as though the turbo frame tags are setup correctly given that the model instances are present and appending. The problem is that additional instances of the model are only appending when I fully refresh the page. They are not appending automatically, as would be expected with a proper Hotwire setup. I have my the source HTML attached as a screenshot.

It’s really aggravating as this same general setup is working perfectly in my prototypes.

Both this app and my last prototype used webpacker, so I don’t believe that happens to be the issue. Perhaps it is a webpacker issue generally though? Any thoughts on how I’d best investigate that?

Thanks for taking the time to reply. I really appreciate it!

Under the network tab in your browser I’d turn on preserve log, then refresh and look for any 404 or failed web sockets.

If you have an active job adapter like sidekiq or resque make sure it’s running

In your screen shot I see turbo_frame > turbo_frame

We’re those dynamically inserted or rendered on refresh?

Hi Chris.

So I started preserving all the logs and then added a new story instance. There doesn’t appear to be any errors in the logs indicating a problem.

Once I refresh the page the new story instance appears as it would in a normal CRUD implementation. To answer your question more directly, the turbo_frame tags nested inside of the parent turbo_frame tag all render on refresh. For some reason they just don’t append dynamically/automatically (which is of course what I’m trying to achieve).

I don’t have any active job adapters but I do have a Redis server running in the background. Apparently this is needed to support Hotwire. I’ve attached screenshots of both the preserved logs and Redis.

Thank you again for your valuable time.

I think I usually see turbo-stream in the type column in my stuff when things are working. Maybe these logs didn’t include a form submit?

Are you seeing turbo requests on normal page navigation?

Maybe also check your webpack-dev-server output to make sure there’s not an error that prevented newest assets from being built

Dang. You are correct. This is the log for my prototype app where the Hotwire activity is working correctly. Completely different log behaviour.

EDIT: And no, I don’t see any turbo requests on any page navigation at all for the non-prototype app I’m working on. : \

Okay, I will check that out next and see what I find.

Could it be a CSP issue?

In our app, because we’re using strict script_src and style_src settings, to inject JS that comes after the initial page load, we added:

# config/initializers/content_security_policy.rb
Rails.application.config.content_security_policy_nonce_generator = ->(request) do
    request.env["HTTP_X_TURBOLINKS_NONCE"].presence || SecureRandom.base64(16)
// app/javascript/packs/application.js
document.addEventListener("turbo:before-fetch-request", function (event) {
  const cspNonce = document

  event.detail.fetchOptions.headers["X-Turbolinks-Nonce"] = cspNonce

document.addEventListener("turbo:before-cache", function () {
    .forEach((element) => element.setAttribute("nonce", element.nonce))
    .forEach((element) => element.setAttribute("nonce", element.nonce))

I wanted to circle back to this post to report that I didn’t find a solution. This is despite spending over a week’s worth of full-time hours trying to debug this problem.

In the end it was just faster and easier to start a new repo with the latest version of Ruby, Rails, and all of the gems. I proceeded to simply copy and paste as much code as I could into the new repo. Beyond that, I retraced my steps with my terminal commands and basically created a clone of the original app.

Lo and behold, it works.

The new app uses Ruby version 3.0.1 and Rails version The old iteration of the app (the one that isn’t working) runs on Ruby version 2.7.1 and Rails version

Thank you to everyone who reached out to try and help me in this matter.

1 Like