Sorry - a bit of a long response below.

> Okay everyone ... this 'debate' got going on another thread I started.
> 
> I've used React before and have found using Turbo frames and Stimulus to be 
> like a breath of fresh air, especially how well they integrate with the rest 
> of the Rails stack. 
> 
> Other people have said that it can quickly get messy and React is needed for 
> anything complex.

I've been building a big Rails monolith using extensive Hotwire over the last 
three years.  

When I started out there wasn't a huge amount of documentation on how to use it 
and I got a bit over-excited with the turbo-stream and broadcast stuff as I 
wanted live updates everywhere.  

That was a mistake and some bits of the code are a mess.  

My biggest issue is the Broadcastable mixin for ActiveRecord models.  

According to the docs, you should use them within ActiveRecord callbacks, which 
are quite coarse-grained.  

For example, my system shows documents in folders.  If you rename the document, 
any partials showing that document need to be updated.  But if you move a 
document from one folder to another, the document's folder_id has changed, but 
the document itself doesn't need to update.  Instead, the original folder needs 
a "broadcast removed" notification and the new folder needs a "broadcast 
append".  So you either 1) skip the model broadcasts and do everything in 
controllers (which, as my system has user-configurable actions that happen in 
the background, will mean missing updates that should have been sent), 2) add 
in complex `after_commit` callbacks to your models that vary their behaviour 
based on attributes that have changed, or 3) pepper your model's methods with 
view-related code.  

Another issue is because broadcasts happen outside the normal request cycle you 
don't have access to the `current_user`.  This means that you end up sending 
the same HTML to everyone, so you can't show/hide bits of the views based on 
the user's permissions or context.  Or you could add the user_id to the stream 
identifier, have the model enumerate every user who might be interested and 
send each one a unique broadcast.  Or do what some of my older code does and 
send a broadcast that is actually a lazy turbo-frame, so it re-requests the 
view in the context of a normal request.  

To deal with this, I've built my own observer system.  I use ViewComponents 
instead of partials, and most ViewComponents take a user parameter (so it 
doesn't matter if they are rendered outside the request cycle).  They then 
register themselves and the events they are interested in with my "Observatory" 
class (which in turn stores the user_id and any other model ids needed in 
Redis).  My models' methods can send fine-grained notifications (such as 
folder#document_removed or folder#document_added as well as the usual 
coarse-grained document#updated) to the Observatory, which finds the interested 
components, reinstantiates them with the new state and sends that user-specific 
HTML only to the relevant clients.  

It works and the theory of it is pretty good - but the code itself was written 
in a hurry, is overly complex and very messy.  

It's basically the same as publishing model-specific channels sending 
fine-grained notifications over a web-socket.  Each React (or whatever) 
component can subscribe to the relevant channels and update itself as needed.  
But in that scenario, the component state is all stored on the client so it can 
easily redraw itself.  Whereas with the Observatory, I need to store and 
retrieve the state elsewhere so I can render the correct HTML.  

Finally, if I were starting over, I would skip 90% of the turbo stream stuff - 
broadcasts and partial page updates.  Turbo 8 uses morphing so full page 
reloads no longer lose all your front-end state.  Which means as long as your 
controller responses are fast enough you get many of the benefits of frames and 
streams without the complexity.  It's a shame to miss out on the live updates 
everywhere though.  

Baz

(Stimulus is great though)

-- 
You received this message because you are subscribed to the Google Groups 
"North West Ruby User Group (NWRUG)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to nwrug-members+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/nwrug-members/D65BF3AA-C61E-4C24-87A4-15BA08D05E83%40gmail.com.

Reply via email to