Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: '22'
cache: 'npm'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/generators.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
name: ${{ matrix.framework }} (TS:${{ matrix.typescript }}, TW:${{ matrix.tailwind }}, Inertia:${{ matrix.inertia_version }})

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Set up Ruby
uses: ruby/setup-ruby@v1
Expand All @@ -42,7 +42,7 @@ jobs:
run: bundle exec rspec --tag type:generator

- name: Set up Node
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}

Expand All @@ -69,7 +69,7 @@ jobs:

- name: Upload test artifacts
if: failure()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: test-output-${{ matrix.framework }}-ts${{ matrix.typescript }}-tw${{ matrix.tailwind }}-v${{ matrix.inertia_version }}
path: |
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ jobs:
runs-on: ubuntu-latest
name: Linter
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3"
ruby-version: "3.4"
bundler: latest
bundler-cache: true
- name: Run RuboCop
Expand Down Expand Up @@ -53,21 +53,21 @@ jobs:
name: Test against Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }}

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6

- name: Setup System
run: sudo apt-get install libsqlite3-dev

- name: Set up Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: 22.x

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
rubygems: latest
rubygems: 'latest'
bundler-cache: true
env:
RAILS_VERSION: ${{ matrix.rails }}
Expand Down
1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ gemspec
version = ENV.fetch('RAILS_VERSION', '8.1')
gem 'rails', "~> #{version}.0"

gem 'bundler', '~> 2.0'
gem 'debug'
gem 'generator_spec', '~> 0.10'
gem 'rails-controller-testing'
Expand Down
2 changes: 1 addition & 1 deletion app/views/inertia.html.erb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<div id="app" data-page="<%= page.to_json %>"></div>
<%= inertia_root(page: page) %>
3 changes: 3 additions & 0 deletions docs/guide/client-side-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,6 @@ createInertiaApp({
// ...
})
```

> [!NOTE]
> Make sure the [`root_dom_id`](/guide/configuration#root_dom_id) configuration option matches the `id` property in your client-side setup.
56 changes: 56 additions & 0 deletions docs/guide/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,59 @@ The default value will be changed to `true` in the next major version.
Specifies the base controller class for the internal `StaticController` used to render [Shorthand routes](/guide/routing#shorthand-routes).

By default, Inertia Rails creates a `StaticController` that inherits from `ApplicationController`. You can use this option to specify a different base controller (for example, to include custom authentication, layout, or before actions).

### `root_dom_id`

**Default**: `'app'`
**ENV**: `INERTIA_ROOT_DOM_ID`

@available_since rails=master

Specifies the DOM element ID used for the root Inertia.js element.

```ruby
InertiaRails.configure do |config|
config.root_dom_id = 'inertia-app'
end
```

> [!NOTE]
> Make sure your client-side Inertia setup uses the same ID when calling `createInertiaApp`.

### `use_script_element_for_initial_page`

**Default**: `false`
**ENV**: `INERTIA_USE_SCRIPT_ELEMENT_FOR_INITIAL_PAGE`

@available_since rails=master core=master

When enabled the initial page data is rendered in a `<script type="application/json">` element instead of the `data-page` attribute on the root `<div>`.
This provides two main benefits:

1. **Smaller page size**: JSON data doesn't require HTML entity encoding, reducing the overall HTML payload size.
2. **Faster parsing**: The browser can parse raw JSON directly from the script element, which is more efficient than parsing HTML-encoded JSON from an attribute.

```ruby
InertiaRails.configure do |config|
config.use_script_element_for_initial_page = true
end
```

When disabled (default), the HTML output looks like:

```html
<div id="app" data-page='{"component":"Users/Index",...}'></div>
```

When enabled, the HTML output looks like:

```html
<script data-page="app" type="application/json">
{"component":"Users/Index",...}
</script>
<div id="app"></div>
```

> [!NOTE]
> When using this option make sure your client-side Inertia setup is configured to read the page data from the `<script>` element.
> See the [protocol documentation](/guide/the-protocol#html-responses) for more details.
76 changes: 71 additions & 5 deletions docs/guide/responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,85 @@ Please note that if you manually provide a props hash in your render call, the i

## Root template data

There are situations where you may want to access your prop data in your ERB template. For example, you may want to add a meta description tag, Twitter card meta tags, or Facebook Open Graph meta tags. You can access this data via the `page` method.
There are situations where you may want to access your prop data in your ERB template. For example, you may want to add a meta description tag, Twitter card meta tags, or Facebook Open Graph meta tags.

Inertia Rails provides several view helpers for working with Inertia data in your templates:

### `inertia_page`

Returns the [page object](/guide/the-protocol#the-page-object) hash containing `component`, `props`, `url`, and other Inertia data. Use this to access page data in your root template.

```erb
# app/views/inertia.html.erb

<% content_for(:head) do %>
<meta name="twitter:title" content="<%= page["props"]["event"].title %>">
<meta name="twitter:title" content="<%= inertia_page[:props][:event][:title] %>">
<% end %>

<div id="app" data-page="<%= page.to_json %>"></div>
<%= inertia_root %>
```

Sometimes you may even want to provide data to the root template that will not be sent to your JavaScript page / component. This can be accomplished by passing the `view_data` option.
### `inertia_rendering?`

Returns `true` when the current request is rendering an Inertia response. This is useful for conditionally rendering content in shared layouts.

```erb
# app/views/layouts/application.html.erb

<% if inertia_rendering? %>
<%= yield %>
<% else %>
<div class="traditional-layout">
<%= yield %>
</div>
<% end %>
```

### `inertia_root`

Renders the root element for the Inertia app. This helper automatically respects the [`root_dom_id`](/guide/configuration#root_dom_id) and [`use_script_element_for_initial_page`](/guide/configuration#use_script_element_for_initial_page) configuration options.

```erb
<%= inertia_root %>
```

You can also pass a custom `id` or `page` object if needed:

```erb
<%= inertia_root(id: 'my-app', page: custom_page_object) %>
```

### `inertia_ssr_head`

Returns the SSR head content when [server-side rendering](/guide/server-side-rendering) is enabled. This should be included in your layout's `<head>` section to inject SSR-generated meta tags and other head elements.

```erb
# app/views/layouts/inertia.html.erb

<!DOCTYPE html>
<html>
<head>
<%= inertia_ssr_head %>
</head>
<body>
<%= yield %>
</body>
</html>
```

### `inertia_meta_tags`

Renders meta tags that were defined server-side using the `inertia_meta` configuration. This is useful for SEO when you want to manage meta tags from your Rails controllers. See the [Server-managed meta tags cookbook](/cookbook/server-managed-meta-tags) for a complete guide.

```erb
<head>
<%= inertia_meta_tags %>
</head>
```

### Passing additional data to the view

Sometimes you may want to provide data to the root template that will not be sent to your JavaScript page / component. This can be accomplished by passing the `view_data` option.

```ruby
def show
Expand All @@ -120,7 +186,7 @@ You can then access this variable like a regular local variable.
content="<%= local_assigns.fetch(:meta, "Default description") %>">
<% end %>

<div id="app" data-page="<%= page.to_json %>"></div>
<%= inertia_root %>
```

## Rails generators
Expand Down
27 changes: 27 additions & 0 deletions docs/guide/the-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,33 @@ Content-Type: text/html; charset=utf-8
</html>
```

### Script element alternative

As an alternative the page data can be rendered in a `<script type="application/json">` element instead of the `data-page` attribute.
This approach provides smaller page sizes (no HTML entity encoding required) and faster JSON parsing by the browser.

```html
<script data-page="app" type="application/json">
{
"component": "Event",
"props": {
"errors": {},
"event": {
"id": 80,
"title": "Birthday party",
"start_date": "2019-06-02",
"description": "Come out and celebrate Jonathan's 36th birthday party!"
}
},
"url": "/events/80",
"version": "c32b8e4965f418ad16eaebba1d4e960f"
}
</script>
<div id="app"></div>
```

See the [`use_script_element_for_initial_page`](/guide/configuration#use_script_element_for_initial_page) configuration option to enable this behavior.

While the initial response is HTML, Inertia does not server-side render the JavaScript page components. For information on server-side rendering, see the [SSR documentation](/guide/server-side-rendering).

## Inertia responses
Expand Down
1 change: 1 addition & 0 deletions lib/generators/inertia/install/templates/initializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
config.version = ViteRuby.digest
config.encrypt_history = true
config.always_include_errors_hash = true
config.use_script_element_for_initial_page = true
end
6 changes: 6 additions & 0 deletions lib/inertia_rails/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class Configuration

# Whether to include empty `errors` hash to the props when no errors are present.
always_include_errors_hash: nil,

# Whether to use `<script>` element for initial page rendering instead of the `data-page` attribute.
use_script_element_for_initial_page: false,

# DOM id to use for the root Inertia.js element.
root_dom_id: 'app',
}.freeze

OPTION_NAMES = DEFAULTS.keys.freeze
Expand Down
14 changes: 14 additions & 0 deletions lib/inertia_rails/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,19 @@ def inertia_meta_tags

safe_join(meta_tags, "\n")
end

def inertia_root(id: nil, page: inertia_page)
config = controller.send(:inertia_configuration)
id ||= config.root_dom_id

if config.use_script_element_for_initial_page
safe_join([
tag.script(page.to_json.html_safe, 'data-page': id, type: 'application/json'),
tag.div(id: id)
], "\n")
else
tag.div(id: id, 'data-page': page.to_json)
end
end
end
end
Loading