### Install turbo-rails Gem and Configure Action Cable
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Provides instructions for installing the `turbo-rails` gem and configuring Action Cable for real-time features. It includes adding the gem to the Gemfile, running the installer, and configuring Redis for development and production environments.
```ruby
# Gemfile
gem "turbo-rails"
# Run installer
# $ rails turbo:install
# config/cable.yml (for development with Redis)
development:
adapter: redis
url: redis://localhost:6379/1
production:
adapter: redis
url: <%= ENV.fetch("REDIS_URL") %>
# app/javascript/application.js
import "@hotwired/turbo-rails"
# For importmap-rails (config/importmap.rb)
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
# config/environments/test.rb (configure auto-connect behavior)
config.turbo.test_connect_after_actions = [:visit, :click_link]
```
--------------------------------
### Install Turbo-Rails Gem
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
Add the turbo-rails gem to your application's Gemfile to include Turbo functionality. This is a prerequisite for manual installation on Rails 6.
```ruby
gem 'turbo-rails'
```
--------------------------------
### Create Turbo Frames with `turbo_frame_tag` (ERB)
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
These ERB examples demonstrate how to use the `turbo_frame_tag` helper to define frames within your HTML. When a link within a frame is clicked, Turbo replaces only that frame's content with the response from the server.
```erb
<%# app/views/todos/show.html.erb %>
<%= turbo_frame_tag @todo do %>
<%= @todo.description %>
<%= link_to 'Edit this todo', edit_todo_path(@todo) %>
<% end %>
<%# app/views/todos/edit.html.erb %>
<%= turbo_frame_tag @todo do %>
<%= render "form" %>
<%= link_to 'Cancel', todo_path(@todo) %>
<% end %>
```
--------------------------------
### Initialize and Use Turbo JavaScript API
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Demonstrates how to import and use the Turbo JavaScript API for programmatic control of Turbo Drive, Frames, and Streams. It shows global availability, disabling Drive, programmatic navigation, cache control, and event listeners.
```javascript
// Import in your application.js (done automatically by turbo-rails)
import "@hotwired/turbo-rails"
// Turbo is available globally
console.log(window.Turbo)
// Disable Turbo Drive globally
Turbo.session.drive = false
// Programmatic navigation
Turbo.visit("/articles")
Turbo.visit("/articles", { action: "replace" }) // Replace history
Turbo.visit("/articles", { action: "advance" }) // Push to history
// Cache control
Turbo.cache.clear()
// Listen to Turbo events
document.addEventListener("turbo:load", (event) => {
console.log("Page loaded:", event.detail.url)
})
document.addEventListener("turbo:before-visit", (event) => {
if (!confirm("Leave this page?")) {
event.preventDefault()
}
})
document.addEventListener("turbo:frame-load", (event) => {
console.log("Frame loaded:", event.target.id)
})
document.addEventListener("turbo:before-stream-render", (event) => {
// Customize stream rendering
const { action, target } = event.detail.newStream
console.log(`Stream action: ${action} on ${target}`)
})
// Using the cable module for custom subscriptions
import { cable } from "@hotwired/turbo-rails"
const subscription = await cable.subscribeTo("CustomChannel", {
received(data) {
console.log("Received:", data)
}
})
```
--------------------------------
### Controller Integration for Turbo Frames and Native Apps (Ruby)
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Demonstrates how to integrate Turbo Rails helpers within Rails controllers. It shows handling Turbo Frame requests, including detecting frame requests and using minimal layouts. It also illustrates native app navigation helpers for hybrid apps, managing redirects and dismissals based on the client type.
```ruby
class ArticlesController < ApplicationController
def show
@article = Article.find(params[:id])
end
def edit
@article = Article.find(params[:id])
# Turbo Frame requests automatically use minimal layout
end
def create
@article = Article.new(article_params)
if @article.save
respond_to do |format|
format.turbo_stream # renders create.turbo_stream.erb
format.html { redirect_to @article, notice: "Created!" }
end
else
render :new, status: :unprocessable_entity
end
end
def update
@article = Article.find(params[:id])
if @article.update(article_params)
respond_to do |format|
format.turbo_stream do
render turbo_stream: turbo_stream.replace(@article)
end
format.html { redirect_to @article }
end
else
render :edit, status: :unprocessable_entity
end
end
def destroy
@article = Article.find(params[:id])
@article.destroy
respond_to do |format|
format.turbo_stream { render turbo_stream: turbo_stream.remove(@article) }
format.html { redirect_to articles_url }
end
end
private
# Detect if request is from a Turbo Frame
def frame_request_check
if turbo_frame_request?
# Request came from within a
@frame_id = turbo_frame_request_id
end
end
end
# Custom layout handling for Turbo Frames
class DashboardController < ApplicationController
layout :choose_layout
private
def choose_layout
return "turbo_rails/frame" if turbo_frame_request?
"dashboard"
end
end
class PostsController < ApplicationController
def create
@post = Post.create!(post_params)
# Dismiss modal in native app, redirect on web
recede_or_redirect_to posts_path, notice: "Post created!"
end
def update
@post = Post.find(params[:id])
@post.update!(post_params)
# Ignore in native app (let it handle), redirect on web
resume_or_redirect_to @post
end
def mark_read
@post = Post.find(params[:id])
@post.mark_as_read!
# Refresh current screen in native app, redirect on web
refresh_or_redirect_to @post
end
def cancel
# Use back navigation when available
recede_or_redirect_back_or_to posts_path
end
private
def check_native_app
if hotwire_native_app?
# Request is from Hotwire Native iOS or Android app
# turbo_native_app? is an alias
end
end
end
```
--------------------------------
### Import Turbo JavaScript
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
Import the Turbo JavaScript module into your application. This makes the Turbo instance automatically available globally as `window.Turbo`.
```javascript
import "@hotwired/turbo-rails"
```
--------------------------------
### Import Turbo Cable Consumer
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
If using Node.js and requiring the cable consumer, import it specifically from the turbo module. Ensure that imported members are actually used to avoid potential issues.
```javascript
import { cable } from "@hotwired/turbo-rails"
```
--------------------------------
### Test Turbo Stream Broadcasts with Connection Wait (Ruby)
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
This Ruby snippet illustrates how to test Turbo Stream broadcasts in a Rails System Test. It includes the `connect_turbo_cable_stream_sources` helper to ensure that WebSocket connections are established before asserting on broadcasted content, preventing race conditions.
```ruby
test "renders broadcasted Messages" do
message = Message.new content: "Hello, from Action Cable"
visit "/"
click_link "All Messages"
connect_turbo_cable_stream_sources
message.save! # execute server-side code to broadcast a Message
assert_text message.content
end
```
--------------------------------
### Turbo Stream From Helper in ERB
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Creates a subscription to a Turbo Streams channel using Action Cable. It renders a `` element with a signed stream name for secure, real-time server-pushed updates. Supports multiple streamables and custom Action Cable channels.
```erb
<%# Subscribe to updates for a specific model %>
<%= turbo_stream_from @message %>
<%# Client will receive broadcasts to stream "message_1" %>
<%# Subscribe with multiple streamables for namespaced streams %>
<%= turbo_stream_from Current.account, :entries %>
<%# Client will receive broadcasts to stream "account_5_entries" %>
<%# Using custom Action Cable channel %>
<%= turbo_stream_from "room", channel: RoomChannel %>
<%# With additional data attributes for the channel %>
<%= turbo_stream_from "room", channel: RoomChannel, data: { room_name: "General" } %>
<%# In a chat room view %>
<%# app/views/rooms/show.html.erb %>
<%= turbo_stream_from @room %>
<%= render @room.messages %>
```
--------------------------------
### Implement Turbo Stream Source (ERB)
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
This ERB snippet demonstrates how to use the `turbo_stream_from` helper to create a Turbo Stream source in a Rails view. This allows the view to subscribe to asynchronous updates delivered over a WebSocket connection, enabling partial page updates.
```erb
<%# app/views/todos/show.html.erb %>
<%= turbo_stream_from dom_id(@todo) %>
<%# Rest of show here %>
```
--------------------------------
### Turbo Rails Controller Helpers for Frame Updates
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Demonstrates how to respond to form submissions with inline Turbo Stream updates using controller helpers. This pattern is common for creating dynamic user interfaces where form submissions trigger partial page refreshes.
```ruby
class MessagesController < ApplicationController
def create
@message = Message.new(message_params)
if @message.save
respond_to do |format|
format.html { redirect_to @message }
format.turbo_stream
end
else
# Handle errors
end
end
private
def message_params
params.require(:message).permit(:content)
end
end
```
--------------------------------
### Render Templates Outside Request Cycle in Rails
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
Demonstrates how to render Turbo-aware templates, partials, or components outside of the request-response cycle using ActionController::Renderer. This is useful for background jobs or other non-request contexts. It shows direct usage of the renderer and a shortcut via the controller class.
```ruby
ApplicationController.renderer.render template: "posts/show", assigns: { post: Post.first } # => "…"
PostsController.renderer.render :show, assigns: { post: Post.first } # => "…"
ApplicationController.render template: "posts/show", assigns: { post: Post.first } # => "…"
PostsController.render :show, assigns: { post: Post.first } # => "…"
```
--------------------------------
### Configure Turbo Test Connection Behavior (Ruby)
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
This Ruby snippet shows how to configure Turbo's test connection behavior in `config/environments/test.rb`. It demonstrates how to specify which Capybara actions should automatically wait for Turbo Cable stream sources to connect, or disable this behavior entirely.
```ruby
# config/environments/test.rb
config.turbo.test_connect_after_actions << :click_link
```
```ruby
# config/environments/test.rb
config.turbo.test_connect_after_actions = []
```
--------------------------------
### Link Local Turbo Version in Rails Project
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
Instructions for linking a local development version of the Turbo library into a Turbo-Rails project using Yarn's link feature. This allows for testing local changes to Turbo itself within a Rails application. It involves linking Turbo globally and then linking it into the specific Rails project, followed by building the JavaScript distribution files.
```sh
cd
yarn link
cd
yarn link @hotwired/turbo
# Build the JS distribution files...
yarn build
# ...and commit the changes
```
--------------------------------
### Model Broadcasting with Turbo::Broadcastable (Ruby)
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Enables models to broadcast Turbo Stream updates via Action Cable. Updates can be sent synchronously or asynchronously using ActiveJob. This concern simplifies broadcasting on create, update, and destroy, or allows for custom configurations.
```ruby
# app/models/message.rb
class Message < ApplicationRecord
belongs_to :room
# Automatic broadcasts on create/update/destroy
broadcasts_to :room
# Or with custom configuration
broadcasts_to ->(message) { [message.room, :messages] },
inserts_by: :prepend,
target: "room_messages",
partial: "messages/message"
# For page refresh broadcasts (works with morphing)
broadcasts_refreshes_to :room
end
# Manual broadcasting from model callbacks
class Comment < ApplicationRecord
belongs_to :post
after_create_commit :broadcast_new_comment
after_update_commit :broadcast_update
after_destroy_commit :broadcast_removal
private
def broadcast_new_comment
# Asynchronous append (recommended for callbacks)
broadcast_append_later_to post, :comments,
target: "post_#{post.id}_comments",
partial: "comments/comment",
locals: { comment: self }
end
def broadcast_update
# Synchronous replace
broadcast_replace_to post, :comments
end
def broadcast_removal
# Remove is always synchronous (no rendering needed)
broadcast_remove_to post, :comments
end
end
# Broadcasting from anywhere (controller, job, etc.)
class MessagesController < ApplicationController
def create
@message = @room.messages.create!(message_params)
# Direct broadcast via channel
Turbo::StreamsChannel.broadcast_append_to(
@room,
target: "messages",
partial: "messages/message",
locals: { message: @message }
)
respond_to do |format|
format.turbo_stream
format.html { redirect_to @room }
end
end
end
# Broadcast page refresh
class Article < ApplicationRecord
after_update_commit :broadcast_refresh_later
private
def broadcast_refresh_later
broadcast_refresh_later_to self
end
end
# Suppressing broadcasts temporarily
Message.suppressing_turbo_broadcasts do
Message.create!(content: "This won't broadcast")
end
```
--------------------------------
### Test Real-time Updates with Turbo in Rails System Tests
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Tests the real-time update functionality using Turbo in system tests. It visits a room, connects to Turbo Cable streams, and then asserts that new messages are displayed in real-time after being created.
```ruby
class MessagesSystemTest < ApplicationSystemTestCase
include Turbo::SystemTestHelper
test "receives real-time updates" do
room = rooms(:general)
visit room_path(room)
# Wait for WebSocket connection before triggering broadcast
connect_turbo_cable_stream_sources
# Trigger broadcast (e.g., from another session)
Message.create!(room: room, content: "Real-time!")
assert_text "Real-time!"
end
end
```
--------------------------------
### Importing Turbo-Rails in Pack File
Source: https://github.com/hotwired/turbo-rails/blob/main/UPGRADING.md
This JavaScript code snippet shows how to import the Turbo-Rails library in your application's pack file. It replaces the older `require("turbolinks").start()` with a modern ES module import. Turbo is automatically initialized upon import.
```javascript
import "@hotwired/turbo-rails"
```
--------------------------------
### Turbo Rails View Helpers
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Provides view helpers for Turbo Frames and Turbo Streams, enabling partial page updates and real-time DOM manipulation within Rails applications. These helpers are essential for structuring your views to leverage Turbo's capabilities.
```erb
<%= turbo_frame_tag "new_message" do %>
<% end %>
<%= turbo_stream_from "messages" %>
```
--------------------------------
### Turbo Drive Behavior Configuration (ERB)
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Configures Turbo Drive behavior using view helpers within ERB templates. These helpers generate meta tags to control page caching, previewing, and refresh strategies, influencing how Turbo navigates between pages.
```erb
<%# app/views/layouts/application.html.erb %>
<%= yield :head %>
<%= yield %>
<%# app/views/checkout/show.html.erb %>
<%# Prevent Turbo from caching this page %>
<% turbo_exempts_page_from_cache %>
<%# app/views/dashboard/index.html.erb %>
<%# Don't show cached preview during navigation %>
<% turbo_exempts_page_from_preview %>
<%# app/views/settings/edit.html.erb %>
<%# Force full page reload when visiting this page %>
<% turbo_page_requires_reload %>
<%# app/views/posts/show.html.erb %>
<%# Configure page refresh behavior (for broadcast_refresh) %>
<% turbo_refreshes_with method: :morph, scroll: :preserve %>
<%# Or use tag variants directly %>
<%= turbo_exempts_page_from_cache_tag %>
<%= turbo_refresh_method_tag(:morph) %>
<%= turbo_refresh_scroll_tag(:preserve) %>
```
--------------------------------
### Configure Custom Layout for Turbo Frame Requests (Ruby)
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
This snippet shows how to define a custom layout method in Rails to conditionally render Turbo frame requests without the application layout. It ensures that `turbo_rails/frame` is returned for Turbo frame requests, while falling back to other custom layouts otherwise.
```ruby
layout :custom_layout
def custom_layout
return "turbo_rails/frame" if turbo_frame_request?
# ... your custom layout logic
end
```
```ruby
layout :custom_layout
def custom_layout
return "turbo_rails/frame" if turbo_frame_request?
"some_static_layout"
end
```
--------------------------------
### Turbo-Rails Assertions Helper for Integration Tests
Source: https://github.com/hotwired/turbo-rails/blob/main/UPGRADING.md
This Ruby code defines a helper module `TurboAssertionsHelper` for `ActionDispatch::IntegrationTest` to assert Turbo Drive redirections. It overrides `assert_redirected_to` to check for Turbo visits when `turbo_request?` is true, and provides `assert_turbo_visited` for specific Turbo visit assertions. It relies on regular expressions to parse Turbo visit calls.
```ruby
module TurboAssertionsHelper
TURBO_VISIT = /Turbo\.visit\(\"([^\"]+)\", \{"action\":\"([^\"]+)\"\}\)/
def assert_redirected_to(options = {}, message = nil)
if turbo_request?
assert_turbo_visited(options, message)
else
super
end
end
def assert_turbo_visited(options = {}, message = nil)
assert_response(:ok, message)
assert_equal("text/javascript", response.try(:media_type) || response.content_type)
visit_location, _ = turbo_visit_location_and_action
redirect_is = normalize_argument_to_redirection(visit_location)
redirect_expected = normalize_argument_to_redirection(options)
message ||= "Expected response to be a Turbo visit to <#{redirect_expected}> but was a visit to <#{redirect_is}>")
assert_operator redirect_expected, :===, redirect_is, message
end
# Rough heuristic to detect whether this was a Turbolinks request:
# non-GET request with a text/javascript response.
#
# Technically we'd check that Turbolinks-Referrer request header is
# also set, but that'd require us to pass the header from post/patch/etc
# test methods by overriding them to provide a `turbo:` option.
#
# We can't check `request.xhr?` here, either, since the X-Requested-With
# header is cleared after controller action processing to prevent it
# from leaking into subsequent requests.
def turbo_request?
!request.get? && (response.try(:media_type) || response.content_type) == "text/javascript"
end
def turbo_visit_location_and_action
if response.body =~ TURBO_VISIT
[ $1, $2 ]
end
end
end
```
--------------------------------
### Disable Turbo Drive by Default (JavaScript)
Source: https://github.com/hotwired/turbo-rails/blob/main/README.md
This snippet shows how to disable Turbo Drive globally by default in your JavaScript import. You can then selectively enable it on a per-element basis using `data-turbo="true"`.
```javascript
import "@hotwired/turbo-rails"
Turbo.session.drive = false
```
--------------------------------
### Turbo Test Assertions (Ruby)
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Provides Ruby test helpers for asserting the presence and content of Turbo Stream and Turbo Frame elements within rendered HTML and Action Cable broadcasts. These are crucial for verifying Turbo-related functionality in tests.
```ruby
# No code provided for this section in the input text.
```
--------------------------------
### Test Turbo Stream Responses in Rails Controllers
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Tests controller actions to verify the response format and content when returning a Turbo Stream. It asserts the response status, specific Turbo Stream actions (append, remove), and inspects the stream content using `assert_select`.
```ruby
class MessagesControllerTest < ActionDispatch::IntegrationTest
test "create returns turbo stream response" do
room = rooms(:general)
post room_messages_url(room),
params: { message: { content: "Hello" } },
as: :turbo_stream
assert_response :success
# Assert specific turbo stream action
assert_turbo_stream action: "append", target: "messages"
# Assert with block for content inspection
assert_turbo_stream action: "append", target: "messages" do
assert_select "template div.message", text: /Hello/
end
# Assert turbo stream is NOT present
assert_no_turbo_stream action: "remove", target: "messages"
end
end
```
--------------------------------
### Javascript Shim for Turbolinks to Turbo Mobile Adapters
Source: https://github.com/hotwired/turbo-rails/blob/main/UPGRADING.md
This Javascript code acts as a compatibility shim, translating calls made to the `window.Turbolinks` object to their equivalent functions in the `Turbo` object. It is particularly useful for older mobile applications that relied on Turbolinks adapters and need to migrate to Turbo without breaking existing functionality. It handles visit operations, adapter registration, and event dispatching.
```javascript
// Compatibility shim for mobile apps
window.Turbolinks = {
visit: Turbo.visit,
controller: {
isDeprecatedAdapter(adapter) {
return typeof adapter.visitProposedToLocation !== "function"
},
startVisitToLocationWithAction(location, action, restorationIdentifier) {
window.Turbo.navigator.startVisit(location, restorationIdentifier, { action })
},
get restorationIdentifier() {
return window.Turbo.navigator.restorationIdentifier
},
get adapter() {
return window.Turbo.navigator.adapter
},
set adapter(adapter) {
if (this.isDeprecatedAdapter(adapter)) {
// Old mobile adapters do not support visitProposedToLocation()
adapter.visitProposedToLocation = function(location, options) {
adapter.visitProposedToLocationWithAction(location, options.action)
}
// Old mobile adapters use visit.location.absoluteURL, which is not available
// because Turbo dropped the Location class in favor of the DOM URL API
const adapterVisitStarted = adapter.visitStarted
adapter.visitStarted = function(visit) {
Object.defineProperties(visit.location, {
absoluteURL: {
configurable: true,
get() {
return this.toString()
}
}
})
adapter.currentVisit = visit
adapterVisitStarted(visit)
}
}
window.Turbo.registerAdapter(adapter)
}
}
}
// Required by the desktop app
document.addEventListener("turbo:load", function() {
const event = new CustomEvent("turbolinks:load", { bubbles: true })
document.documentElement.dispatchEvent(event)
})
```
--------------------------------
### Turbo Stream Actions for DOM Manipulation (ERB)
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Generates Turbo Stream action tags for various DOM manipulations like remove, append, prepend, replace, update, before, after, and refresh. These actions are typically used in `.turbo_stream.erb` views. They can target elements by DOM ID, Active Record object, or CSS selector.
```erb
<%# Remove an element by DOM ID %>
<%= turbo_stream.remove "flash_notice" %>
<%# Output: %>
<%# Remove using Active Record object %>
<%= turbo_stream.remove @message %>
<%# Output: %>
<%# Append content to a container %>
<%= turbo_stream.append "messages", @message %>
<%# Output: ...rendered partial... %>
<%# Prepend with custom partial %>
<%= turbo_stream.prepend "messages", partial: "messages/message", locals: { message: @message } %>
<%# Replace an element with new content %>
<%= turbo_stream.replace @message do %>
<%= @message.content %>
<% end %>
<%# Update inner HTML (keeps the target element, replaces children) %>
<%= turbo_stream.update "message_count", "#{@messages.count} messages" %>
<%# Insert before a specific element %>
<%= turbo_stream.before "message_5" do %>
New message inserted before
<% end %>
<%# Insert after a specific element %>
<%= turbo_stream.after @message, partial: "messages/reply_form" %>
<%# Target multiple elements with CSS selector %>
<%= turbo_stream.remove_all ".notification" %>
<%= turbo_stream.update_all ".counter", "0" %>
<%# Trigger page refresh (uses morphing if configured) %>
<%= turbo_stream.refresh %>
<%# Output: %>
<%# Replace with morphing for smoother updates %>
<%= turbo_stream.replace @message, method: :morph %>
```
--------------------------------
### Test Turbo Stream Broadcasts in Rails Controllers
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Tests controller actions to verify that Turbo Streams are broadcasted correctly. It uses `assert_turbo_stream_broadcasts` to check for broadcasts within a block of code that triggers the broadcast.
```ruby
class MessagesControllerTest < ActionDispatch::IntegrationTest
test "create broadcasts message" do
room = rooms(:general)
assert_turbo_stream_broadcasts room do
post room_messages_url(room), params: { message: { content: "Hello" } }
end
end
end
```
--------------------------------
### Capture and Inspect Turbo Stream Broadcasts in Rails Models
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Tests the ability to capture and inspect Turbo Stream broadcasts within a model context. It uses `capture_turbo_stream_broadcasts` to collect broadcasted streams and then asserts their actions and content.
```ruby
class MessageTest < ActiveSupport::TestCase
include Turbo::Broadcastable::TestHelper
test "capture and inspect broadcasts" do
room = rooms(:general)
message = Message.create!(room: room, content: "Test")
streams = capture_turbo_stream_broadcasts room do
message.broadcast_append_to room
message.broadcast_remove_to room
end
assert_equal 2, streams.length
assert_equal "append", streams.first["action"]
assert_equal "remove", streams.second["action"]
end
end
```
--------------------------------
### Turbo Rails Model Concerns for Broadcasting
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Enables automatic broadcasting of model changes using the `Turbo::Broadcastable` concern. This allows real-time updates to be sent to subscribed clients when model records are created, updated, or destroyed.
```ruby
class Message < ApplicationRecord
include Turbo::Broadcastable
after_create_commit do
broadcast_append_later_to "messages", partial: "messages/message", locals: { message: self }
end
end
```
--------------------------------
### Test Turbo Frame Rendering in Rails Controllers
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Tests controller actions to verify that Turbo Frames are rendered correctly. It uses `assert_turbo_frame` to check for the presence of specific frames by ID or Active Record object, and can also assert frame attributes like `src` and `loading`.
```ruby
class MessagesControllerTest < ActionDispatch::IntegrationTest
test "show renders turbo frame" do
message = messages(:hello)
get message_url(message)
assert_turbo_frame "message_#{message.id}"
assert_turbo_frame message # Using Active Record object
# With attributes
assert_turbo_frame "lazy_content", src: "/load", loading: "lazy"
# Assert frame NOT present
assert_no_turbo_frame "nonexistent"
end
end
```
--------------------------------
### Test Turbo Stream Broadcasts in Rails Models
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Tests model behavior to ensure Turbo Streams are broadcasted upon creation. It uses `assert_turbo_stream_broadcasts` to verify that a single broadcast occurs when a new record is created.
```ruby
class MessageTest < ActiveSupport::TestCase
include Turbo::Broadcastable::TestHelper
test "broadcasts on create" do
room = rooms(:general)
assert_turbo_stream_broadcasts room, count: 1 do
Message.create!(room: room, content: "Hello")
end
end
end
```
--------------------------------
### Default 422 Error Page Styling (CSS)
Source: https://github.com/hotwired/turbo-rails/blob/main/test/dummy/public/422.html
Provides the CSS styles for the default 422 Unprocessable Entity error page in Turbo Rails applications. This styling is applied to enhance the readability and presentation of error messages to users.
```css
.rails-default-error-page { background-color: #EFEFEF; color: #2E2F30; text-align: center; font-family: arial, sans-serif; margin: 0; }
.rails-default-error-page div.dialog { width: 95%; max-width: 33em; margin: 4em auto 0; }
.rails-default-error-page div.dialog > div { border: 1px solid #CCC; border-right-color: #999; border-left-color: #999; border-bottom-color: #BBB; border-top: #B00100 solid 4px; border-top-left-radius: 9px; border-top-right-radius: 9px; background-color: white; padding: 7px 12% 0; box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); }
.rails-default-error-page h1 { font-size: 100%; color: #730E15; line-height: 1.5em; }
.rails-default-error-page div.dialog > p { margin: 0 0 1em; padding: 1em; background-color: #F7F7F7; border: 1px solid #CCC; border-right-color: #999; border-left-color: #999; border-bottom-color: #999; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-color: #DADADA; color: #666; box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); }
```
--------------------------------
### Turbo Frame Tag Helper in ERB
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Generates `` elements for encapsulating content or lazy-loading from a URL. It automatically creates DOM IDs from Active Record objects and supports targeting other frames or the entire page.
```erb
<%# Basic frame with string ID %>
<%= turbo_frame_tag "tray" do %>
Content inside the frame
<% end %>
<%# Output: Content inside the frame
%>
<%# Lazy-loading frame that fetches content from URL %>
<%= turbo_frame_tag "tray", src: tray_path(@tray), loading: "lazy" %>
<%# Output: %>
<%# Frame with Active Record object (auto-generates DOM ID) %>
<%= turbo_frame_tag @article do %>
<%= @article.title %>
<%= link_to "Edit", edit_article_path(@article) %>
<% end %>
<%# Output: Title
... %>
<%# Frame targeting another frame or the entire page %>
<%= turbo_frame_tag @article, target: "_top" do %>
<%= link_to "View Full Page", article_path(@article) %>
<% end %>
<%# Nested ID generation %>
<%= turbo_frame_tag [@user, "profile"] %>
<%# Output: %>
```
--------------------------------
### Rotate Active Storage Keys in Turbo Rails
Source: https://github.com/hotwired/turbo-rails/blob/main/UPGRADING.md
This code snippet rotates Active Storage keys to ensure previously stored assets remain accessible after upgrading Turbo Rails versions. It's placed in `config/initializers` and uses `ActiveSupport::KeyGenerator` to create a new key based on SHA1.
```ruby
Rails.application.config.after_initialize do |app|
key_generator = ActiveSupport::KeyGenerator.new app.secret_key_base,
iterations: 1000,
hash_digest_class: OpenSSL::Digest::SHA1
app.message_verifier("ActiveStorage").rotate(key_generator.generate_key("ActiveStorage"))
end
```
--------------------------------
### Configure SHA1 Digest Class in Turbo Rails
Source: https://github.com/hotwired/turbo-rails/blob/main/UPGRADING.md
This configuration snippet overrides the default key generation digest class to SHA1. This can be used as an alternative to key rotation if your application is affected by the digest changes in Turbo Rails 1.1.1.
```ruby
config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA1
```
--------------------------------
### Turbo-Rails Redirection Concern for Controllers
Source: https://github.com/hotwired/turbo-rails/blob/main/UPGRADING.md
This Ruby code defines a concern `Turbo::Redirection` to be included in `ApplicationController`. It overrides the `redirect_to` method to handle Turbo Drive redirections for XHR requests, ensuring compatibility with 302 responses. It requires `ActiveSupport::Concern` and `request.xhr?`.
```ruby
module Turbo
module Redirection
extend ActiveSupport::Concern
def redirect_to(url = {}, options = {})
turbo = options.delete(:turbo)
super.tap do
if turbo != false && request.xhr? && !request.get?
visit_location_with_turbo(location, turbo)
end
end
end
private
def visit_location_with_turbo(location, action)
visit_options = {
action: action.to_s == "advance" ? action : "replace"
}
script = []
script << "Turbo.cache.clear()"
script << "Turbo.visit(#{
location.to_json
}, #{visit_options.to_json})"
self.status = 200
self.response_body = script.join("\n")
response.content_type = "text/javascript"
response.headers["X-Xhr-Redirect"] = location
end
end
end
```
--------------------------------
### Test Suppressed Turbo Stream Broadcasts in Rails Models
Source: https://context7.com/hotwired/turbo-rails/llms.txt
Tests model behavior to ensure Turbo Streams are not broadcasted when explicitly suppressed. It uses `assert_no_turbo_stream_broadcasts` in conjunction with `Message.suppressing_turbo_broadcasts` to verify that no broadcasts occur.
```ruby
class MessageTest < ActiveSupport::TestCase
include Turbo::Broadcastable::TestHelper
test "no broadcast when suppressed" do
room = rooms(:general)
assert_no_turbo_stream_broadcasts room do
Message.suppressing_turbo_broadcasts do
Message.create!(room: room, content: "Silent")
end
end
end
end
```
--------------------------------
### Disable Remote Form Generation in Rails Application
Source: https://github.com/hotwired/turbo-rails/blob/main/UPGRADING.md
This configuration setting in `config/application.rb` disables the default behavior of `form_with` generating remote forms. It's a necessary step when switching from Rails UJS/Turbolinks to Turbo to avoid conflicts.
```ruby
config.action_view.form_with_generates_remote_forms = false
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.