-
Notifications
You must be signed in to change notification settings - Fork 486
Description
tl;dr:
In ActionCable Context, don't use the class method ApplicationController.render(component, layout: nil). This triggers layout rendering in broadcast context and causes unexpected errors. Use the instance method instead: ApplicationController.renderer.new.render(component). This is unexpected for me
Steps to reproduce
- Create a ViewComponent to render in ActionCable broadcasts
- Use ApplicationController.render(component, layout: nil) inside a broadcast method
- Observe that the full application layout renders despite layout: nil
Code example:
# In a broadcast method (ActiveRecord callback, service, etc.)
def broadcast_notification(notification)
Turbo::StreamsChannel.broadcast_prepend_to(
stream_name,
target: 'notification-list',
content: ApplicationController.render(
NotificationComponent.new(notification: notification),
layout: nil # ← This is ignored
)
)
end
Expected behavior
The component should render without the application layout, producing only the component HTML.
Actual behavior
The full layouts/application.html.erb renders around the component, causing:
- Unexpected rendering of layout partials
- Errors from unrelated components in the layout
- Log output showing "Rendering layout layouts/application.html.erb"
Rails logs confirm layout rendering:
Rendering layout layouts/application.html.erb
Rendering NotificationComponent within layouts/application
Workaround
Using ApplicationController.renderer.new.render(component) works correctly:
def broadcast_notification(notification)
Turbo::StreamsChannel.broadcast_prepend_to(
stream_name,
target: 'notification-list',
content: ApplicationController.renderer.new.render(
NotificationComponent.new(notification: notification)
)
)
end
This produces only component HTML without layout, as expected.
Analysis
The class method ApplicationController.render() appears to behave differently than the instance method chain ApplicationController.renderer.new.render() when called outside an HTTP request context (ActionCable broadcasts, background jobs, etc.). The layout: option isn't properly respected for ViewComponents in these contexts.
System configuration
- Rails version: 8.1.1
- Ruby version: 3.4.1
- ViewComponent version: 4.1.1