Cellane

Cellane

Agile Web Development with Rails 8: live product refresh not working in chapter 11

Hello, I was struggling a bit with completing chapter 11, iteration F4.

While the changes done in the “admin” (maintenance?) panel to store products showed up without me refreshing the main store page, it didn’t feel as smooth as it should have – the entire page refreshed, instead of just morphing the DOM to contain the new data. After spending a few hours investigating this, I found two root causes that should probably be addressed in the final book:

The entire rendering process is crashing due to not being able to render the product partial

This issue can be observed either from the terminal, where I could see this output (truncated):

02:38:35 web.1  | Started GET "/products/7" for ::1 at 2025-02-20 02:38:35 +0900
02:38:35 web.1  | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [40cc8022-d8d7-4b62-9fcb-053676ba5413]   Product Load (0.2ms)  SELECT "products".* FROM "products" WHERE "products"."id" = 7 LIMIT 1 /*application='Depot'*/
02:38:35 web.1  | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [40cc8022-d8d7-4b62-9fcb-053676ba5413] Performing Turbo::Streams::ActionBroadcastJob (Job ID: 40cc8022-d8d7-4b62-9fcb-053676ba5413) from Async(default) enqueued at 2025-02-19T17:38:35.448256000Z with arguments: "products", {action: :replace, target: "product_7", targets: nil, attributes: {}, partial: "store/product", locals: {product: #<GlobalID:0x0000000138317188 @uri=#<URI::GID gid://depot/Product/7>>}}
02:38:35 web.1  | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [40cc8022-d8d7-4b62-9fcb-053676ba5413]   ActiveStorage::Attachment Load (0.1ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = 7 AND "active_storage_attachments"."record_type" = 'Product' AND "active_storage_attachments"."name" = 'image' LIMIT 1 /*application='Depot',job='Turbo%3A%3AStreams%3A%3AActionBroadcastJob'*/
02:38:35 web.1  | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [40cc8022-d8d7-4b62-9fcb-053676ba5413]   ↳ app/views/store/_product.html.erb:3
02:38:35 web.1  | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [40cc8022-d8d7-4b62-9fcb-053676ba5413]   ActiveStorage::Blob Load (0.0ms)  SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = 7 LIMIT 1 /*application='Depot',job='Turbo%3A%3AStreams%3A%3AActionBroadcastJob'*/
02:38:35 web.1  | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [40cc8022-d8d7-4b62-9fcb-053676ba5413]   ↳ app/views/store/_product.html.erb:3
02:38:35 web.1  | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [40cc8022-d8d7-4b62-9fcb-053676ba5413]   Disk Storage (0.9ms) Generated URL for file at key: v7g25mgxk84oj9sxzjdpjyafgygx ()
02:38:35 web.1  | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [40cc8022-d8d7-4b62-9fcb-053676ba5413]   Rendered store/_product.html.erb (Duration: 7.0ms | GC: 0.0ms)
02:38:35 web.1  | [ActiveJob] [Turbo::Streams::ActionBroadcastJob] [40cc8022-d8d7-4b62-9fcb-053676ba5413] Error performing Turbo::Streams::ActionBroadcastJob (Job ID: 40cc8022-d8d7-4b62-9fcb-053676ba5413) from Async(default) in 12.4ms: ActionView::Template::Error (Cannot generate URL for nrclient2.jpg using Disk service, please set ActiveStorage::Current.url_options.):
02:38:35 web.1  | /Users/milan/.local/share/mise/installs/ruby/3.4.1/lib/ruby/gems/3.4.0/gems/activestorage-8.0.1/lib/active_storage/service/disk_service.rb:138:in 'ActiveStorage::Service::DiskService#generate_url'
02:38:35 web.1  | /Users/milan/.local/share/mise/installs/ruby/3.4.1/lib/ruby/gems/3.4.0/gems/activestorage-8.0.1/lib/active_storage/service/disk_service.rb:117:in 'ActiveStorage::Service::DiskService#private_url'
02:38:35 web.1  | /Users/milan/.local/share/mise/installs/ruby/3.4.1/lib/ruby/gems/3.4.0/gems/activestorage-8.0.1/lib/active_storage/service.rb:125:in 'block in ActiveStorage::Service#url'
02:38:35 web.1  | /Users/milan/.local/share/mise/installs/ruby/3.4.1/lib/ruby/gems/3.4.0/gems/activesupport-8.0.1/lib/active_support/notifications.rb:210:in 'block in ActiveSupport::Notifications.instrument'
02:38:35 web.1  | /Users/milan/.local/share/mise/installs/ruby/3.4.1/lib/ruby/gems/3.4.0/gems/activesupport-8.0.1/lib/active_support/notifications/instrumenter.rb:58:in 'ActiveSupport::Notifications::Instrumenter#instrument'

Or in the browser’s developer console, where you can see the store main page unsubscribing from the WebSocket topic and resubscribing back to it – which should not happen. Also, the entire page just very obviously jumps, as it would if there was a full page reload happening.

Based on the error message, I thought that something akin to include ActiveStorage::SetCurrent that we previously added to ApplicationController also needs to be added to ApplicationCable::Channel but that doesn’t seem to be the case, as the solution is much simpler – the store/_product partial needs to be changed instead:

-    <%= image_tag(product.image.url, class: "object-contain w-40 h-48 shadow mr-6") %>
+    <%= image_tag(product.image, class: "object-contain w-40 h-48 shadow mr-6") %>

After this, the crash no longer happens in the server console, but the page still hard-refreshes. That’s because…

The WebSockets topics overlap with chapter 6

Chapter 6 adds after_commit -> { broadcast_refresh_later_to "products" }, introducing the products topic, and then chapter 11 reuses the topic to broadcast not the information to refresh the page, but to replace the affected part. I think these should not share the same topic, so after changing ProductsChannel like so:

-    stream_from "products"
+    stream_from "store/products"

ProductsController like so:

-        @product.broadcast_replace_later_to "products", partial: "store/product"
+        @product.broadcast_replace_later_to "store/products", partial: "store/product"

… and store’s view template like so:

- <%= turbo_stream_from "products" %>
+ <%= turbo_stream_from "store/products" %>

… everything starts working smoothly again, no full-page refreshes happen, and only the affected product gets replaced.

That was a fun one to figure out, as a Rails newbie! :face_with_hand_over_mouth:

(Also I feel like earlier in the chapter, the customer said to please honour the price of the product at the time of adding the product to the cart and I don’t think that’s happening yet but maybe it will be addressed later in the chapter…? Or maybe just not written yet, should probably involve putting the price on LineItem and copying the value over at the time of adding it to the cart.) I missed that this is part of the optional exercises on pages 144~145. My bad!

Marked As Solved

rubys

rubys

Author of Agile Web Development With Rails

Good catch, and good suggestion! And glad you are having fun! Thanks!

Where Next?

Popular Pragmatic Bookshelf topics Top

abtin
page 20: … protoc command… I had to additionally run the following go get commands in order to be able to compile protobuf code using go...
New
jamis
The following is cross-posted from the original Ray Tracer Challenge forum, from a post by garfieldnate. I’m cross-posting it so that the...
New
herminiotorres
Hi! I know not the intentions behind this narrative when called, on page XI: mount() |&gt; handle_event() |&gt; render() but the correc...
New
alanq
This isn’t directly about the book contents so maybe not the right forum…but in some of the code apps (e.g. turbo/06) it sends a TURBO_ST...
New
swlaschin
The book has the same “Problem space/Solution space” diagram on page 18 as is on page 17. The correct Problem/Solution space diagrams ar...
New
leba0495
Hello! Thanks for the great book. I was attempting the Trie (chap 17) exercises and for number 4 the solution provided for the autocorre...
New
adamwoolhether
When trying to generate the protobuf .go file, I receive this error: Unknown flag: --go_opt libprotoc 3.12.3 MacOS 11.3.1 Googling ...
New
adamwoolhether
I’m not quite sure what’s going on here, but I’m unable to have to containers successfully complete the Readiness/Liveness checks. I’m im...
New
redconfetti
Docker-Machine became part of the Docker Toolbox, which was deprecated in 2020, long after Docker Desktop supported Docker Engine nativel...
New
dachristenson
@mfazio23 Android Studio will not accept anything I do when trying to use the Transformations class, as described on pp. 140-141. Googl...
New

Other popular topics Top

New
DevotionGeo
I know that these benchmarks might not be the exact picture of real-world scenario, but still I expect a Rust web framework performing a ...
New
AstonJ
Or looking forward to? :nerd_face:
498 13979 272
New
Rainer
My first contact with Erlang was about 2 years ago when I used RabbitMQ, which is written in Erlang, for my job. This made me curious and...
New
Exadra37
I am asking for any distro that only has the bare-bones to be able to get a shell in the server and then just install the packages as we ...
New
AstonJ
Saw this on TikTok of all places! :lol: Anyone heard of them before? Lite:
New
New
DevotionGeo
I have always used antique keyboards like Cherry MX 1800 or Cherry MX 8100 and almost always have modified the switches in some way, like...
New
New
PragmaticBookshelf
Explore the power of Ash Framework by modeling and building the domain for a real-world web application. Rebecca Le @sevenseacat and ...
New

Sub Categories: