### 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: %> <%# 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.