If ActionCable isn't working properly in your environment, StimulusReflex cannot function.
Step one to any troubleshooting process should be "is it plugged in?"
rails generate channel test in your Rails project folder. This will ensure that your ActionCable setup has been initialized, although you should verify that in your
import 'channels' present.
Next, copy and paste the following into the two specified files, replacing their contents.
app/channels/test_channel.rbclass TestChannel < ApplicationCable::Channeldef subscribedstream_from "test"enddef receive(data)puts data["message"]ActionCable.server.broadcast("test", "ActionCable is connected")endend
If ActionCable is running properly, you should see
ActionCable is connected in your browser's Console Inspector and
Client is live in your server's STDOUT log stream.
You can feel free to remove both of these files after you're done, but leave
Once your app is properly configured and off to a good start, you might want to consider disabling ActionCable logging by setting the following in an initializer:
config/initializers/action_cable.rbActionCable.server.config.logger = Logger.new(nil)
Not only is the ActionCable logger particularly verbose - especially when you're doing full-page morph operations - but it's widely understood to be a source of mystery slowdowns.
There is an abundance of collected wisdom on the StimulusReflex Deployment documentation page for developers who are working with ActionCable.
Another excellent resource is the Sidekiq wiki page for Heroku.
TL;DR: there's some awesome shortcuts for StimulusReflex developers to use CableReady to broadcast operations to the current user, but they come at the expense of introducing a gotcha. We think that they are totally worth it, but we still feel bad when folks occasionally lose time to this.
... if the goal is to show the current user something new.
In Rails, the order of operations is Request -> Controller Action -> View Render -> Response. If you broadcast a CableReady operation targeting the current user during the Controller Action phase, it will transmit to the browser and execute before the HTML has even been rendered. This leads to an unfortunate scenario where it appears that "nothing happened."
If your controller action has created an event that should be broadcast to multiple people, such as an event notification, it makes sense to broadcast that data as soon as it's relevant - ideally, via an ActiveJob so you can return your HTML faster.
Similarly, controller actions that don't initiate a navigation event (Ajax actions, webhooks, OAuth endpoints) are all fine to broadcast.
Note that if this group broadcast would modify the page state of the initiating user, the DOM generated by the Controller Action should reflect the new state as though you also received the broadcast. It's easier to deliver perfect HTML up front, rather than wasting time trying to receive an event on the client. See "The Logical Splitter".
Architecturally, this is like throwing turd away before sprinting to try and catch it. 💩
There are some who have been trained to loudly reject what they see as violations of the barrier between business logic and presentation layer in their applications. Much like stop signs and poison labels, the intentions behind these constraints are almost always a really good idea. Most of the time, you should go with the program when it comes to things designed to keep you safe.
There are situations, however, whether the only rational decision is to consciously ignore the generalized advice and be confident that you can explain why you did so. Otherwise, you're just slave to a dogma.
A poignant example of this is the conundrum of an ActiveJob broadcasting HTML updates to the DOM. Which solution sounds sane to you?
ActiveJob uses CableReady to broadcast a dispatch_event operation with a custom event name and resource id attached as
detail. The event is picked up by a DOM element with a Stimulus controller which immediately calls
this.stimulate('Insane#hoop_jump', id) which triggers a Selector Reflex that renders a partial and uses CableReady to send a
morph operation which updates the DOM element.
ActiveJob uses CableReady to send a
morph operation which updates the DOM element.
Don't be the person who performs a Server -> Client -> Server -> Client ritual so that you can claim you kept your business logic separate from filthy presentation layer concerns. That's not architectural purity, it's wasting some of the time you have left before you die. ⏳
If you have Stimulus running on your application, you should consider installing radiolabel. It is a Stimulus controller that watches for CableReady "after-operation" events. When it detects an operation that mutates an element, it will create a titled overlay which briefly announces when an element is modified.
morph operations will be orange, while all others are green.
If you're doing a lot of DOM manipulation with CableReady, you'll find radiolabel to be indispensable.