From 3ae8c8c867aa37a74f1c3c987d215f60d5f9c844 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kryukov Date: Sat, 21 Jun 2025 18:51:21 +0300 Subject: [PATCH 1/2] Docs: improve searchability by naming methods --- docs/guide/asset-versioning.md | 2 +- docs/guide/client-side-setup.md | 2 +- docs/guide/configuration.md | 4 ++-- docs/guide/csrf-protection.md | 4 ++-- docs/guide/deferred-props.md | 4 ++-- docs/guide/forms.md | 2 +- docs/guide/history-encryption.md | 35 +++++++++++++++++++++++++++++--- docs/guide/manual-visits.md | 9 ++++---- docs/guide/responses.md | 6 +++--- docs/guide/testing.md | 2 ++ 10 files changed, 50 insertions(+), 20 deletions(-) diff --git a/docs/guide/asset-versioning.md b/docs/guide/asset-versioning.md index 18f48e28..ea398126 100644 --- a/docs/guide/asset-versioning.md +++ b/docs/guide/asset-versioning.md @@ -4,7 +4,7 @@ One common challenge when building single-page apps is refreshing site assets wh ## Configuration -To enable automatic asset refreshing, you need to tell Inertia the current version of your assets. This can be any arbitrary string (letters, numbers, or a file hash), as long as it changes when your assets have been updated. +To enable automatic asset refreshing, you need to tell Inertia the current version of your assets using the `InertiaRails.configure` method and setting the `config.version` property. This can be any arbitrary string (letters, numbers, or a file hash), as long as it changes when your assets have been updated. ```ruby InertiaRails.configure do |config| diff --git a/docs/guide/client-side-setup.md b/docs/guide/client-side-setup.md index 1953c6d4..9029720d 100644 --- a/docs/guide/client-side-setup.md +++ b/docs/guide/client-side-setup.md @@ -32,7 +32,7 @@ npm install @inertiajs/svelte svelte ## Initialize the Inertia app -Next, update your main JavaScript file to boot your Inertia app. To accomplish this, we'll initialize the client-side framework with the base Inertia component. +Next, update your main JavaScript file to boot your Inertia app. To accomplish this, we'll use the `createInertiaApp` function to initialize the client-side framework with the base Inertia component. :::tabs key:frameworks == Vue diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 8c3281b9..9be7c58e 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -4,7 +4,7 @@ Inertia Rails can be configured globally or in a specific controller (and subcla ## Global Configuration -If using global configuration, we recommend you place the code inside an initializer: +Use the `InertiaRails.configure` method to set global configuration options. If using global configuration, we recommend you place the code inside an initializer: ```ruby # config/initializers/inertia.rb @@ -19,7 +19,7 @@ The default configuration can be found [here](https://github.com/inertiajs/inert ## Local Configuration -Use `inertia_config` in your controllers to override global settings: +The `inertia_config` method allows you to override global settings in specific controllers. Use this method in your controllers to customize configuration for specific parts of your application: ```ruby class EventsController < ApplicationController diff --git a/docs/guide/csrf-protection.md b/docs/guide/csrf-protection.md index d95d0c07..68b16ebb 100644 --- a/docs/guide/csrf-protection.md +++ b/docs/guide/csrf-protection.md @@ -4,7 +4,7 @@ Inertia's Rails adapter automatically includes the proper CSRF token when making requests via Inertia or Axios. Therefore, **no additional configuration is required**. -However, if you need to handle CSRF protection manually, one approach is to include the CSRF token as a prop on every response. You can then use the token when making Inertia requests. +However, if you need to handle CSRF protection manually, one approach is to include the CSRF token as a prop on every response. You can then use the token when making Inertia requests with the `router.post` method. :::tabs key:frameworks == Vue @@ -67,7 +67,7 @@ When a CSRF token mismatch occurs, Rails raises the `ActionController::InvalidAu Obviously, this isn't a great user experience. A better way to handle these errors is to return a redirect back to the previous page, along with a flash message that the page expired. This will result in a valid Inertia response with the flash message available as a prop which you can then display to the user. Of course, you'll need to share your [flash messages](/guide/shared-data.md#flash-messages) with Inertia for this to work. -You may modify your application's exception handler to automatically redirect the user back to the page they were previously on while flashing a message to the session. To accomplish this, you may use the `rescue_from` method in your `ApplicationController`. +You may modify your application's exception handler to automatically redirect the user back to the page they were previously on while flashing a message to the session. To accomplish this, you may use the `rescue_from` method in your `ApplicationController` to handle the `ActionController::InvalidAuthenticityToken` exception. ```ruby class ApplicationController < ActionController::Base diff --git a/docs/guide/deferred-props.md b/docs/guide/deferred-props.md index 9db7eb63..59a9b172 100644 --- a/docs/guide/deferred-props.md +++ b/docs/guide/deferred-props.md @@ -4,7 +4,7 @@ Inertia's deferred props feature allows you to defer the loading of certain page ## Server side -To defer a prop, you can use the defer method when returning your response. This method receives a callback that returns the prop data. The callback will be executed in a separate request after the initial page render. +To defer a prop, you can use the `InertiaRails.defer` method when returning your response. This method receives a callback that returns the prop data. The callback will be executed in a separate request after the initial page render. ```ruby class UsersController < ApplicationController @@ -20,7 +20,7 @@ end ### Grouping requests -By default, all deferred props get fetched in one request after the initial page is rendered, but you can choose to fetch data in parallel by grouping props together. +By default, all deferred props get fetched in one request after the initial page is rendered, but you can choose to fetch data in parallel by grouping props together using the `group` option with the `InertiaRails.defer` method. ```ruby class UsersController < ApplicationController diff --git a/docs/guide/forms.md b/docs/guide/forms.md index 736230d6..3f7d4d3d 100644 --- a/docs/guide/forms.md +++ b/docs/guide/forms.md @@ -186,7 +186,7 @@ For a full discussion on handling and displaying [validation](/guide/validation. ## Form helper -Since working with forms is so common, Inertia includes a form helper designed to help reduce the amount of boilerplate code needed for handling typical form submissions. +Since working with forms is so common, Inertia includes a form helper designed to help reduce the amount of boilerplate code needed for handling typical form submissions. The `useForm` method provides a convenient way to manage form state, validation, and submission. :::tabs key:frameworks == Vue diff --git a/docs/guide/history-encryption.md b/docs/guide/history-encryption.md index d2efe01e..6746113c 100644 --- a/docs/guide/history-encryption.md +++ b/docs/guide/history-encryption.md @@ -6,7 +6,7 @@ Imagine a scenario where your user is authenticated, browses privileged informat When you instruct Inertia to encrypt your app's history, it uses the browser's built-in [`crypto` api](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) to encrypt the current page's data before pushing it to the history state. We store the corresponding key in the browser's session storage. When the user navigates back to a page, we decrypt the data using the key stored in the session storage. -Once you instruct Inertia to clear your history state, we simply clear the existing key from session storage roll a new one. If we attempt to decrypt the history state with the new key, it will fail an Inertia will make a fresh request back to your server for the page data. +Once you instruct Inertia to clear your history state, we simply clear the existing key from session storage and roll out a new one. If we attempt to decrypt the history state with the new key, it will fail and Inertia will make a fresh request back to your server for the page data. > [!NOTE] > History encryption relies on `window.crypto.subtle` which is only available in secure environments (sites with SSL enabled). @@ -47,7 +47,7 @@ end ## Clearing history -To clear the history state, you can pass the `clear_history` option to the `render` method: +To clear the history state on the server side, you can pass the `clear_history` option to the `render` method: ```ruby render inertia: 'Dashboard', props: {}, clear_history: true @@ -55,4 +55,33 @@ render inertia: 'Dashboard', props: {}, clear_history: true Once the response has rendered on the client, the encryption key will be rotated, rendering the previous history state unreadable. -You can also clear history on the client site by calling `router.clearHistory()`. +### Client-side clearing + +You can also clear history directly on the client side by calling the `router.clearHistory()` method: + +:::tabs key:frameworks +== Vue + +```js +import { router } from '@inertiajs/vue3' + +router.clearHistory() +``` + +== React + +```js +import { router } from '@inertiajs/react' + +router.clearHistory() +``` + +== Svelte 4|Svelte 5 + +```js +import { router } from '@inertiajs/svelte' + +router.clearHistory() +``` + +::: diff --git a/docs/guide/manual-visits.md b/docs/guide/manual-visits.md index 874442fa..1002b6ca 100644 --- a/docs/guide/manual-visits.md +++ b/docs/guide/manual-visits.md @@ -270,15 +270,14 @@ router.post('/users', { == Svelte 4|Svelte 5 ```js - -``` - import { router } from '@inertiajs/svelte' router.post('/users', { -name: 'John Doe', -email: 'john.doe@example.com', + name: 'John Doe', + email: 'john.doe@example.com', }) +``` + ::: ## Custom headers diff --git a/docs/guide/responses.md b/docs/guide/responses.md index 825dd229..4d0615b1 100644 --- a/docs/guide/responses.md +++ b/docs/guide/responses.md @@ -139,7 +139,7 @@ Inertia Rails provides a number of generators to help you get started with Inert ### Scaffold generator -To create a resource with Inertia responses, execute the following command in the terminal: +Use the `inertia:scaffold` generator to create a resource with Inertia responses. Execute the following command in the terminal: ```bash bin/rails generate inertia:scaffold ModelName field1:type field2:type @@ -185,7 +185,7 @@ Inertia Rails tries to detect the presence of Tailwind CSS in the application an ### Controller generator -To create a controller with an Inertia response, execute the following command in the terminal: +Use the `inertia:controller` generator to create a controller with an Inertia response. Execute the following command in the terminal: ```bash bin/rails generate inertia:controller ControllerName action1 action2 @@ -211,7 +211,7 @@ $ bin/rails generate inertia:controller pages welcome next_steps ### Customizing the generator templates -Rails generators allow templates customization. For example, to customize the controller generator view template, create a file `lib/templates/inertia_templates/controller/react/view.jsx.tt`: +Rails generators allow templates customization. You can create custom template files in your application to override the default templates used by the generators. For example, to customize the controller generator view template for React, create a file at the path `lib/templates/inertia_templates/controller/react/view.jsx.tt`: ```jsx export default function <%= @action.camelize %>() { diff --git a/docs/guide/testing.md b/docs/guide/testing.md index 02851bd8..41bdde09 100644 --- a/docs/guide/testing.md +++ b/docs/guide/testing.md @@ -35,6 +35,8 @@ end ### Assertions +Inertia Rails provides several RSpec matchers for testing Inertia responses. You can use methods like `expect_inertia`, `render_component`, `have_exact_props`, `include_props`, `have_exact_view_data`, and `include_view_data` to test your Inertia responses. + ```ruby # spec/requests/events_spec.rb RSpec.describe '/events', inertia: true do From 7b9ccc9623f69fc08029eb4d6dc39530de126e1e Mon Sep 17 00:00:00 2001 From: Svyatoslav Kryukov Date: Sat, 21 Jun 2025 19:33:32 +0300 Subject: [PATCH 2/2] Add more docs --- docs/guide/responses.md | 98 +++++++++++++++++++++------------------ docs/guide/routing.md | 20 +++++++- docs/guide/shared-data.md | 17 +++++++ 3 files changed, 89 insertions(+), 46 deletions(-) diff --git a/docs/guide/responses.md b/docs/guide/responses.md index 4d0615b1..24205995 100644 --- a/docs/guide/responses.md +++ b/docs/guide/responses.md @@ -23,55 +23,31 @@ Within Rails applications, the `Event/Show` page would typically correspond to t > [!WARNING] > To ensure that pages load quickly, only return the minimum data required for the page. Also, be aware that **all data returned from the controllers will be visible client-side**, so be sure to omit sensitive information. -### Using instance variables as props +### Automatically determine component name -Inertia enables the automatic passing of instance variables as props. This can be achieved by invoking the `use_inertia_instance_props` function in a controller or in a base controller from which other controllers inherit. +You can pass props without specifying a component name: ```ruby -class EventsController < ApplicationController - use_inertia_instance_props - - def index - @events = Event.all - - render inertia: 'Events/Index' +class UsersController < ApplicationController + def show + render inertia: { user: @user } # Will render '../users/show.jsx|vue|svelte' end end ``` -This action automatically passes the `@events` instance variable as the `events` prop to the `Events/Index` page component. - -> [!NOTE] -> Manually providing any props for a response disables the instance props feature for that specific response. - -> [!NOTE] -> Instance props are only included if they are defined **after** the `use_inertia_instance_props` call, hence the order of `before_action` callbacks is crucial. - -### Automatically determine component name - -Rails conventions can be used to automatically render the correct page component by invoking `render inertia: true`: +If the default component path doesn't match your convention, you can define a custom resolution method via the `component_path_resolver` config value. The value should be callable and will receive the path and action parameters, returning a string component path. ```ruby -class EventsController < ApplicationController - use_inertia_instance_props - - def index - @events = Event.all - - render inertia: true +inertia_config( + component_path_resolver: ->(path:, action:) do + "Storefront/#{path.camelize}/#{action.camelize}" end -end +) ``` -This renders the `app/frontend/pages/events/index.(jsx|vue|svelte)` page component and passes the `@events` instance variable as the `events` prop. - -Setting the `default_render` configuration value to `true` establishes this as the default behavior: +### Using instance variables as props -```ruby -InertiaRails.configure do |config| - config.default_render = true -end -``` +Inertia enables the automatic passing of instance variables as props. This can be achieved by invoking the `use_inertia_instance_props` function in a controller or in a base controller from which other controllers inherit. ```ruby class EventsController < ApplicationController @@ -79,21 +55,19 @@ class EventsController < ApplicationController def index @events = Event.all + + render inertia: 'Events/Index' end end ``` -With this configuration, the `app/frontend/pages/events/index.(jsx|vue|svelte)` page component is rendered automatically, passing the `@events` instance variable as the `events` prop. +This action automatically passes the `@events` instance variable as the `events` prop to the `Events/Index` page component. -If the default component path doesn't match your convention, you can define a custom resolution method via the `component_path_resolver` config value. The value should be callable and will receive the path and action parameters, returning a string component path. +> [!NOTE] +> Manually providing any props for a response disables the instance props feature for that specific response. -```ruby -inertia_config( - component_path_resolver: ->(path:, action:) do - "Storefront/#{path.camelize}/#{action.camelize}" - end -) -``` +> [!NOTE] +> Instance props are only included if they are defined **after** the `use_inertia_instance_props` call, hence the order of `before_action` callbacks is crucial. ## Root template data @@ -236,3 +210,37 @@ You can find the default templates in the gem's source code: To enable client-side history navigation, all Inertia server responses are stored in the browser's history state. However, keep in mind that some browsers impose a size limit on how much data can be saved within the history state. For example, [Firefox](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) has a size limit of 16 MiB and throws a `NS_ERROR_ILLEGAL_VALUE` error if you exceed this limit. Typically, this is much more data than you'll ever practically need when building applications. + +## Detecting Inertia Requests + +Controllers can determine if a request was made via Inertia: + +```ruby +def some_action + if request.inertia? + # This is an Inertia request + end + + if request.inertia_partial? + # This is a partial Inertia request + end +end +``` + +## Inertia responses and `respond_to` + +Inertia responses always operate as a `:html` response type. This means that you can use the `respond_to` method to handle JSON requests differently, while still returning Inertia responses: + +```ruby +def some_action + respond_to do |format| + format.html do + render inertia: 'Some/Component', props: { data: 'value' } + end + + format.json do + render json: { message: 'This is a JSON response' } + end + end +end +``` diff --git a/docs/guide/routing.md b/docs/guide/routing.md index ccd63024..c367a4e6 100644 --- a/docs/guide/routing.md +++ b/docs/guide/routing.md @@ -9,7 +9,25 @@ When using Inertia, all of your application's routes are defined server-side. Th If you have a page that doesn't need a corresponding controller method, like an "FAQ" or "about" page, you can route directly to a component via the `inertia` method. ```ruby -inertia 'about' => 'AboutComponent' +# In config/routes.rb +Rails.application.routes.draw do + # Basic usage - maps 'dashboard' URL to 'Dashboard' component + inertia 'dashboard' => 'Dashboard' + + # Using a symbol - infers component name from route + inertia :settings + + # Within namespaces and scopes + namespace :admin do + inertia 'dashboard' => 'Admin/Dashboard' + end + + # Within resource definitions + resources :users do + inertia :activity, on: :member + inertia :statistics, on: :collection + end +end ``` ## Generating URLs diff --git a/docs/guide/shared-data.md b/docs/guide/shared-data.md index a42f09c9..284703be 100644 --- a/docs/guide/shared-data.md +++ b/docs/guide/shared-data.md @@ -26,6 +26,23 @@ class EventsController < ApplicationController end ``` +### Inheritance and Shared Data + +Shared data defined in parent controllers is automatically inherited by child controllers. Child controllers can also override or add to the shared data: + +```ruby +# Parent controller + class ApplicationController < ActionController::Base + inertia_share app_name: 'My App', version: '1.0' +end + +# Child controller +class UsersController < ApplicationController + # Inherits app_name and version, adds/overrides auth + inertia_share auth: -> { { user: current_user } } +end +``` + ### Conditional Sharing You can control when data is shared using Rails-style controller filters. The `inertia_share` method supports these filter options: