├── .github └── workflows │ ├── docs.yml │ ├── generators.yml │ └── push.yml ├── .gitignore ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── app ├── controllers │ └── inertia_rails │ │ └── static_controller.rb └── views │ └── inertia.html.erb ├── bin ├── console ├── generate_scaffold_example └── setup ├── docs ├── .gitignore ├── .prettierignore ├── .vitepress │ ├── config.mts │ ├── theme │ │ ├── frameworksTabs.ts │ │ ├── index.ts │ │ └── style.css │ └── vitepress-plugin-tabs │ │ ├── ruleBlockTab.ts │ │ └── tabsMarkdownPlugin.ts ├── awesome.md ├── cookbook │ ├── handling-validation-error-types.md │ └── integrating-shadcn-ui.md ├── guide │ ├── asset-versioning.md │ ├── authentication.md │ ├── authorization.md │ ├── client-side-setup.md │ ├── code-splitting.md │ ├── configuration.md │ ├── csrf-protection.md │ ├── deferred-props.md │ ├── demo-application.md │ ├── error-handling.md │ ├── events.md │ ├── file-uploads.md │ ├── forms.md │ ├── history-encryption.md │ ├── how-it-works.md │ ├── index.md │ ├── links.md │ ├── load-when-visible.md │ ├── manual-visits.md │ ├── merging-props.md │ ├── pages.md │ ├── partial-reloads.md │ ├── polling.md │ ├── prefetching.md │ ├── progress-indicators.md │ ├── redirects.md │ ├── remembering-state.md │ ├── responses.md │ ├── routing.md │ ├── scroll-management.md │ ├── server-side-rendering.md │ ├── server-side-setup.md │ ├── shared-data.md │ ├── testing.md │ ├── the-protocol.md │ ├── title-and-meta.md │ ├── upgrade-guide.md │ ├── validation.md │ └── who-is-it-for.md ├── index.md ├── package-lock.json ├── package.json ├── prettier.config.js └── public │ ├── favicon.ico │ ├── logo.jpg │ ├── logo.svg │ ├── og_image.jpg │ └── pingcrm.png ├── inertia_rails.gemspec ├── lib ├── generators │ ├── inertia │ │ ├── controller │ │ │ ├── controller_generator.rb │ │ │ └── templates │ │ │ │ └── controller.rb.tt │ │ ├── install │ │ │ ├── frameworks.yml │ │ │ ├── helpers.rb │ │ │ ├── install_generator.rb │ │ │ ├── js_package_manager.rb │ │ │ └── templates │ │ │ │ ├── assets │ │ │ │ ├── inertia.svg │ │ │ │ ├── react.svg │ │ │ │ ├── svelte.svg │ │ │ │ ├── vite_ruby.svg │ │ │ │ └── vue.svg │ │ │ │ ├── controller.rb │ │ │ │ ├── dev │ │ │ │ ├── initializer.rb │ │ │ │ ├── react │ │ │ │ ├── InertiaExample.jsx │ │ │ │ ├── InertiaExample.module.css │ │ │ │ ├── InertiaExample.tsx │ │ │ │ ├── inertia.js │ │ │ │ ├── inertia.ts │ │ │ │ ├── tsconfig.app.json │ │ │ │ ├── tsconfig.json │ │ │ │ ├── tsconfig.node.json │ │ │ │ └── vite-env.d.ts │ │ │ │ ├── svelte │ │ │ │ ├── InertiaExample.svelte │ │ │ │ ├── InertiaExample.ts.svelte │ │ │ │ ├── inertia.js │ │ │ │ ├── inertia.ts.tt │ │ │ │ ├── svelte.config.js │ │ │ │ ├── tsconfig.json │ │ │ │ ├── tsconfig.node.json │ │ │ │ └── vite-env.d.ts │ │ │ │ ├── svelte4 │ │ │ │ ├── InertiaExample.svelte │ │ │ │ ├── InertiaExample.ts.svelte │ │ │ │ ├── inertia.js │ │ │ │ ├── inertia.ts.tt │ │ │ │ ├── svelte.config.js │ │ │ │ ├── tsconfig.json │ │ │ │ ├── tsconfig.node.json │ │ │ │ └── vite-env.d.ts │ │ │ │ ├── tailwind │ │ │ │ └── application.css │ │ │ │ └── vue │ │ │ │ ├── InertiaExample.ts.vue │ │ │ │ ├── InertiaExample.vue │ │ │ │ ├── inertia.js │ │ │ │ ├── inertia.ts │ │ │ │ ├── tsconfig.app.json │ │ │ │ ├── tsconfig.json │ │ │ │ ├── tsconfig.node.json │ │ │ │ └── vite-env.d.ts │ │ ├── scaffold │ │ │ └── scaffold_generator.rb │ │ └── scaffold_controller │ │ │ ├── scaffold_controller_generator.rb │ │ │ └── templates │ │ │ └── controller.rb.tt │ ├── inertia_templates │ │ ├── controller │ │ │ ├── controller_generator.rb │ │ │ └── templates │ │ │ │ ├── react │ │ │ │ ├── view.jsx.tt │ │ │ │ └── view.tsx.tt │ │ │ │ ├── svelte │ │ │ │ └── view.svelte.tt │ │ │ │ ├── svelte4 │ │ │ │ └── view.svelte.tt │ │ │ │ └── vue │ │ │ │ └── view.vue.tt │ │ └── scaffold │ │ │ ├── scaffold_generator.rb │ │ │ └── templates │ │ │ ├── react │ │ │ ├── Edit.jsx.tt │ │ │ ├── Edit.tsx.tt │ │ │ ├── Form.jsx.tt │ │ │ ├── Form.tsx.tt │ │ │ ├── Index.jsx.tt │ │ │ ├── Index.tsx.tt │ │ │ ├── New.jsx.tt │ │ │ ├── New.tsx.tt │ │ │ ├── One.jsx.tt │ │ │ ├── One.tsx.tt │ │ │ ├── Show.jsx.tt │ │ │ ├── Show.tsx.tt │ │ │ └── types.ts.tt │ │ │ ├── svelte │ │ │ ├── Edit.svelte.tt │ │ │ ├── Edit.ts.svelte.tt │ │ │ ├── Form.svelte.tt │ │ │ ├── Form.ts.svelte.tt │ │ │ ├── Index.svelte.tt │ │ │ ├── Index.ts.svelte.tt │ │ │ ├── New.svelte.tt │ │ │ ├── New.ts.svelte.tt │ │ │ ├── One.svelte.tt │ │ │ ├── One.ts.svelte.tt │ │ │ ├── Show.svelte.tt │ │ │ ├── Show.ts.svelte.tt │ │ │ └── types.ts.tt │ │ │ ├── svelte4 │ │ │ ├── Edit.svelte.tt │ │ │ ├── Edit.ts.svelte.tt │ │ │ ├── Form.svelte.tt │ │ │ ├── Form.ts.svelte.tt │ │ │ ├── Index.svelte.tt │ │ │ ├── Index.ts.svelte.tt │ │ │ ├── New.svelte.tt │ │ │ ├── New.ts.svelte.tt │ │ │ ├── One.svelte.tt │ │ │ ├── One.ts.svelte.tt │ │ │ ├── Show.svelte.tt │ │ │ ├── Show.ts.svelte.tt │ │ │ └── types.ts.tt │ │ │ └── vue │ │ │ ├── Edit.ts.vue.tt │ │ │ ├── Edit.vue.tt │ │ │ ├── Form.ts.vue.tt │ │ │ ├── Form.vue.tt │ │ │ ├── Index.ts.vue.tt │ │ │ ├── Index.vue.tt │ │ │ ├── New.ts.vue.tt │ │ │ ├── New.vue.tt │ │ │ ├── One.ts.vue.tt │ │ │ ├── One.vue.tt │ │ │ ├── Show.ts.vue.tt │ │ │ ├── Show.vue.tt │ │ │ └── types.ts.tt │ └── inertia_tw_templates │ │ ├── controller │ │ ├── controller_generator.rb │ │ └── templates │ │ │ ├── react │ │ │ ├── view.jsx.tt │ │ │ └── view.tsx.tt │ │ │ ├── svelte │ │ │ └── view.svelte.tt │ │ │ ├── svelte4 │ │ │ └── view.svelte.tt │ │ │ └── vue │ │ │ └── view.vue.tt │ │ └── scaffold │ │ ├── scaffold_generator.rb │ │ └── templates │ │ ├── react │ │ ├── Edit.jsx.tt │ │ ├── Edit.tsx.tt │ │ ├── Form.jsx.tt │ │ ├── Form.tsx.tt │ │ ├── Index.jsx.tt │ │ ├── Index.tsx.tt │ │ ├── New.jsx.tt │ │ ├── New.tsx.tt │ │ ├── One.jsx.tt │ │ ├── One.tsx.tt │ │ ├── Show.jsx.tt │ │ ├── Show.tsx.tt │ │ └── types.ts.tt │ │ ├── svelte │ │ ├── Edit.svelte.tt │ │ ├── Edit.ts.svelte.tt │ │ ├── Form.svelte.tt │ │ ├── Form.ts.svelte.tt │ │ ├── Index.svelte.tt │ │ ├── Index.ts.svelte.tt │ │ ├── New.svelte.tt │ │ ├── New.ts.svelte.tt │ │ ├── One.svelte.tt │ │ ├── One.ts.svelte.tt │ │ ├── Show.svelte.tt │ │ ├── Show.ts.svelte.tt │ │ └── types.ts.tt │ │ ├── svelte4 │ │ ├── Edit.svelte.tt │ │ ├── Edit.ts.svelte.tt │ │ ├── Form.svelte.tt │ │ ├── Form.ts.svelte.tt │ │ ├── Index.svelte.tt │ │ ├── Index.ts.svelte.tt │ │ ├── New.svelte.tt │ │ ├── New.ts.svelte.tt │ │ ├── One.svelte.tt │ │ ├── One.ts.svelte.tt │ │ ├── Show.svelte.tt │ │ ├── Show.ts.svelte.tt │ │ └── types.ts.tt │ │ └── vue │ │ ├── Edit.ts.vue.tt │ │ ├── Edit.vue.tt │ │ ├── Form.ts.vue.tt │ │ ├── Form.vue.tt │ │ ├── Index.ts.vue.tt │ │ ├── Index.vue.tt │ │ ├── New.ts.vue.tt │ │ ├── New.vue.tt │ │ ├── One.ts.vue.tt │ │ ├── One.vue.tt │ │ ├── Show.ts.vue.tt │ │ ├── Show.vue.tt │ │ └── types.ts.tt ├── inertia_rails.rb ├── inertia_rails │ ├── action_filter.rb │ ├── always_prop.rb │ ├── base_prop.rb │ ├── configuration.rb │ ├── controller.rb │ ├── defer_prop.rb │ ├── engine.rb │ ├── generators │ │ ├── controller_template_base.rb │ │ ├── helper.rb │ │ └── scaffold_template_base.rb │ ├── helper.rb │ ├── ignore_on_first_load_prop.rb │ ├── inertia_rails.rb │ ├── lazy_prop.rb │ ├── merge_prop.rb │ ├── middleware.rb │ ├── optional_prop.rb │ ├── renderer.rb │ ├── rspec.rb │ └── version.rb ├── patches │ ├── better_errors.rb │ ├── debug_exceptions.rb │ ├── debug_exceptions │ │ ├── patch-5-0.rb │ │ └── patch-5-1.rb │ ├── mapper.rb │ └── request.rb └── tasks │ └── inertia_rails.rake └── spec ├── dummy ├── .ruby-version ├── Rakefile ├── app │ ├── controllers │ │ ├── application_controller.rb │ │ ├── concerns │ │ │ └── .keep │ │ ├── inertia_child_share_test_controller.rb │ │ ├── inertia_conditional_sharing_controller.rb │ │ ├── inertia_config_test_controller.rb │ │ ├── inertia_encrypt_history_controller.rb │ │ ├── inertia_lambda_shared_props_controller.rb │ │ ├── inertia_merge_instance_props_controller.rb │ │ ├── inertia_merge_shared_controller.rb │ │ ├── inertia_multithreaded_share_controller.rb │ │ ├── inertia_rails_mimic_controller.rb │ │ ├── inertia_render_test_controller.rb │ │ ├── inertia_responders_test_controller.rb │ │ ├── inertia_session_continuity_test_controller.rb │ │ ├── inertia_share_test_controller.rb │ │ ├── inertia_test_controller.rb │ │ └── transformed_inertia_rails_mimic_controller.rb │ ├── helpers │ │ └── application_helper.rb │ ├── javascript │ │ └── packs │ │ │ └── application.js │ └── views │ │ └── layouts │ │ ├── application.html.erb │ │ ├── conditional.html.erb │ │ └── testing.html.erb ├── bin │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── database.yml │ ├── environment.rb │ ├── environments │ │ ├── development.rb │ │ ├── production.rb │ │ └── test.rb │ ├── initializers │ │ ├── application_controller_renderer.rb │ │ ├── backtrace_silencers.rb │ │ ├── content_security_policy.rb │ │ ├── cookies_serializer.rb │ │ ├── filter_parameter_logging.rb │ │ ├── inflections.rb │ │ ├── mime_types.rb │ │ └── wrap_parameters.rb │ ├── locales │ │ └── en.yml │ ├── puma.rb │ ├── routes.rb │ └── spring.rb ├── log │ ├── .keep │ └── production.log └── public │ ├── 404.html │ ├── 422.html │ ├── 500.html │ ├── apple-touch-icon-precomposed.png │ ├── apple-touch-icon.png │ └── favicon.ico ├── fixtures ├── install_generator │ ├── dummy │ │ ├── Gemfile │ │ ├── app │ │ │ └── views │ │ │ │ └── layouts │ │ │ │ └── application.html.erb │ │ └── config │ │ │ └── routes.rb │ └── with_vite │ │ ├── app │ │ └── views │ │ │ └── layouts │ │ │ └── application.html.erb │ │ ├── config │ │ └── vite.json │ │ ├── package.json │ │ └── vite.config.ts └── package_json_files │ ├── empty_package.json │ ├── react_package.json │ ├── svelte4_package.json │ ├── svelte5_caret_package.json │ ├── svelte5_exact_package.json │ ├── svelte5_tilde_package.json │ ├── tailwind_package.json │ └── vue_package.json ├── generators ├── generators_helper_spec.rb └── install │ └── install_generator_spec.rb ├── inertia ├── action_filter_spec.rb ├── always_prop_spec.rb ├── base_prop_spec.rb ├── conditional_sharing_spec.rb ├── configuration_spec.rb ├── defer_prop_spec.rb ├── encrypt_history_spec.rb ├── error_sharing_spec.rb ├── helper_spec.rb ├── lazy_prop_spec.rb ├── merge_prop_spec.rb ├── middleware_spec.rb ├── rails_mimic_spec.rb ├── rendering_spec.rb ├── request_spec.rb ├── response_spec.rb ├── rspec_helper_spec.rb ├── sharing_spec.rb └── ssr_spec.rb ├── rails_helper.rb ├── spec_helper.rb └── support ├── helper_module.rb └── shared_examples.rb /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Documentation Checks 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - 'docs/**' 9 | - '.github/workflows/docs.yml' 10 | pull_request: 11 | paths: 12 | - 'docs/**' 13 | - '.github/workflows/docs.yml' 14 | 15 | jobs: 16 | check_formatting: 17 | runs-on: ubuntu-latest 18 | name: Check Documentation Formatting 19 | 20 | concurrency: 21 | group: ${{ github.workflow }}-${{ github.ref }} 22 | cancel-in-progress: true 23 | 24 | steps: 25 | - name: Checkout repository 26 | uses: actions/checkout@v4 27 | 28 | - name: Setup Node.js 29 | uses: actions/setup-node@v4 30 | with: 31 | node-version: '22' 32 | cache: 'npm' 33 | cache-dependency-path: './docs/package-lock.json' 34 | 35 | - name: Install dependencies 36 | working-directory: ./docs 37 | run: npm ci 38 | 39 | - name: Check formatting 40 | working-directory: ./docs 41 | run: npm run format:check 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | /.cache/ 10 | /Gemfile.lock 11 | 12 | /spec/dummy/db/*.sqlite3 13 | /spec/dummy/db/*.sqlite3-journal 14 | /spec/dummy/db/log/*.log 15 | /spec/dummy/tmp/ 16 | /spec/dummy/.sass-cache 17 | /spec/dummy/log/ 18 | 19 | # rspec failure tracking 20 | .rspec_status 21 | 22 | # Appraisal 23 | gemfiles/*.gemfile.lock 24 | 25 | # Local files, such as .env.development.local 26 | *.local 27 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --require rails_helper 4 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | AllCops: 4 | TargetRubyVersion: 3.0 5 | NewCops: enable 6 | SuggestExtensions: false 7 | Exclude: 8 | - 'node_modules/**/*' 9 | - 'tmp/**/*' 10 | - 'vendor/**/*' 11 | - '.git/**/*' 12 | - 'docs/**/*' 13 | 14 | Metrics: 15 | Enabled: false 16 | 17 | Style/Documentation: 18 | Enabled: false 19 | 20 | Style/TrailingCommaInHashLiteral: 21 | EnforcedStyleForMultiline: consistent_comma 22 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | # Specify your gem's dependencies in inertia_rails.gemspec 6 | gemspec 7 | 8 | version = ENV['RAILS_VERSION'] || '8.0' 9 | gem 'rails', "~> #{version}.0" 10 | 11 | gem 'bundler', '~> 2.0' 12 | gem 'debug' 13 | gem 'generator_spec', '~> 0.10' 14 | gem 'rails-controller-testing' 15 | gem 'rake', '~> 13.0' 16 | gem 'responders' 17 | gem 'rspec-rails', '~> 6.0' 18 | gem 'rubocop', '~> 1.21' 19 | gem 'sqlite3' 20 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2025 Bellawatt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler/gem_tasks' 4 | require 'rspec/core/rake_task' 5 | 6 | RSpec::Core::RakeTask.new(:spec) 7 | 8 | require 'rubocop/rake_task' 9 | 10 | RuboCop::RakeTask.new 11 | 12 | task default: %i[spec rubocop] 13 | -------------------------------------------------------------------------------- /app/controllers/inertia_rails/static_controller.rb: -------------------------------------------------------------------------------- 1 | module InertiaRails 2 | class StaticController < ::ApplicationController 3 | def static 4 | render inertia: params[:component] 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/views/inertia.html.erb: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "pathname" 4 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 5 | Pathname.new(__FILE__).realpath) 6 | 7 | require "rubygems" 8 | require "bundler/setup" 9 | require "rails/all" 10 | require "inertia_rails" 11 | 12 | require "irb" 13 | IRB.start(__FILE__) 14 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vitepress/dist 3 | .vitepress/cache 4 | -------------------------------------------------------------------------------- /docs/.prettierignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/dist 3 | **/cache 4 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/frameworksTabs.ts: -------------------------------------------------------------------------------- 1 | const localStorageKey = 'vitepress:tabsSharedState' 2 | const ls = typeof localStorage !== 'undefined' ? localStorage : null 3 | 4 | const getLocalStorageValue = (): RecordFind me in <%= @path %>
6 | > 7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /lib/generators/inertia_templates/controller/templates/react/view.tsx.tt: -------------------------------------------------------------------------------- 1 | export default function <%= @action.camelize %>() { 2 | return ( 3 | <> 4 |Find me in <%= @path %>
6 | > 7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /lib/generators/inertia_templates/controller/templates/svelte/view.svelte.tt: -------------------------------------------------------------------------------- 1 |Find me in <%= @path %>
3 | -------------------------------------------------------------------------------- /lib/generators/inertia_templates/controller/templates/svelte4/view.svelte.tt: -------------------------------------------------------------------------------- 1 |Find me in <%= @path %>
3 | -------------------------------------------------------------------------------- /lib/generators/inertia_templates/controller/templates/vue/view.vue.tt: -------------------------------------------------------------------------------- 1 | 2 |Find me in <%= @path %>
4 | 5 | -------------------------------------------------------------------------------- /lib/generators/inertia_templates/scaffold/scaffold_generator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'inertia_rails/generators/scaffold_template_base' 4 | 5 | module InertiaTemplates 6 | module Generators 7 | class ScaffoldGenerator < InertiaRails::Generators::ScaffoldTemplateBase 8 | hide! 9 | source_root File.expand_path('./templates', __dir__) 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /lib/generators/inertia_templates/scaffold/templates/react/Edit.jsx.tt: -------------------------------------------------------------------------------- 1 | import { Head, Link } from '@inertiajs/react' 2 | import Form from './Form' 3 | 4 | export default function Edit({ <%= singular_table_name %> }) { 5 | return ( 6 | <> 7 |{flash.notice}
} 10 | 11 |17 | `}>Show this <%= human_name.downcase %> 18 |
19 |{flash.notice}
} 16 | 17 |23 | `}>Show this <%= human_name.downcase %> 24 |
25 |12 | {flash.notice} 13 |
14 | )} 15 |30 | `} 32 | className="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" 33 | > 34 | Show this <%= human_name.downcase %> 35 | 36 |
37 |13 | 14 |
33 | > 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/react/One.jsx.tt: -------------------------------------------------------------------------------- 1 | export default function <%= inertia_component_name %>({ <%= singular_table_name %> }) { 2 | return ( 3 |
6 | <%= attribute.human_name %>: 7 | <% if attribute.attachment? -%> 8 | {<%= singular_table_name %>.<%= attribute.column_name %> && ( 9 | .<%= attribute.column_name %>.url}>{<%= singular_table_name %>.<%= attribute.column_name %>.filename} 10 | )} 11 |
12 | <% elsif attribute.attachments? -%> 13 | 14 | {<%= singular_table_name %>.<%= attribute.column_name %>.map((file, i) => ( 15 |25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/react/One.tsx.tt: -------------------------------------------------------------------------------- 1 | import { <%= inertia_model_type %> } from './types' 2 | 3 | interface <%= inertia_component_name %>Props { 4 | <%= singular_table_name %>: <%= inertia_model_type %> 5 | } 6 | 7 | export default function <%= inertia_component_name %>({ <%= singular_table_name %> }: <%= inertia_component_name %>Props) { 8 | return ( 9 |
12 | <%= attribute.human_name %>: 13 | <% if attribute.attachment? -%> 14 | {<%= singular_table_name %>.<%= attribute.column_name %> && ( 15 | .<%= attribute.column_name %>.url}>{<%= singular_table_name %>.<%= attribute.column_name %>.filename} 16 | )} 17 |
18 | <% elsif attribute.attachments? -%> 19 | 20 | {<%= singular_table_name %>.<%= attribute.column_name %>.map((file, i) => ( 21 |
31 | )
32 | }
33 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/react/types.ts.tt:
--------------------------------------------------------------------------------
1 | export interface <%= inertia_model_type %> {
2 | id: number
3 | <% attributes.reject(&:password_digest?).each do |attribute| -%>
4 | <%= attribute.column_name %>: <%= ts_type(attribute) %>
5 | <% end -%>
6 | }
7 |
8 | export type <%= inertia_model_form_type %> = Omit<<%= inertia_model_type %>, <%= omit_input_attributes.map { |a| "'#{a}'" }.join(' | ') %>><% if custom_form_attributes.any? -%> & {
9 | <% custom_form_attributes.map do |attribute| -%>
10 | <% if attribute.password_digest? -%>
11 | password: string
12 | password_confirmation: string
13 | <% elsif attribute.attachment? -%>
14 | <%= attribute.column_name %>?: File
15 | <% elsif attribute.attachments? -%>
16 | <%= attribute.column_name %>?: File[]
17 | <% end -%>
18 | <% end -%>
19 | }<% end %>
20 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Edit.svelte.tt:
--------------------------------------------------------------------------------
1 |
18 |
19 |
45 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Edit.ts.svelte.tt:
--------------------------------------------------------------------------------
1 |
19 |
20 |
46 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Index.svelte.tt:
--------------------------------------------------------------------------------
1 |
7 |
8 |
15 | {flash.notice} 16 |
17 | {/if} 18 | 19 |33 | `} 35 | class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" 36 | > 37 | Show this <%= human_name.downcase %> 38 | 39 |
40 | {/each} 41 |
43 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Index.ts.svelte.tt:
--------------------------------------------------------------------------------
1 |
11 |
12 |
19 | {flash.notice} 20 |
21 | {/if} 22 | 23 |37 | `} 39 | class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" 40 | > 41 | Show this <%= human_name.downcase %> 42 | 43 |
44 | {/each} 45 |
47 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte/New.svelte.tt:
--------------------------------------------------------------------------------
1 |
12 |
13 |
33 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte/New.ts.svelte.tt:
--------------------------------------------------------------------------------
1 |
13 |
14 |
34 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/svelte/One.svelte.tt: -------------------------------------------------------------------------------- 1 | 4 | 5 |
8 | <%= attribute.human_name %>: 9 | <% if attribute.attachment? -%> 10 | {#if <%= singular_table_name %>.<%= attribute.column_name %>} 11 | .<%= attribute.column_name %>.url}> 12 | {<%= singular_table_name %>.<%= attribute.column_name %>.filename} 13 | 14 | {/if} 15 |
16 | <% elsif attribute.attachments? -%> 17 | 18 | {#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }} 19 |29 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/svelte/One.ts.svelte.tt: -------------------------------------------------------------------------------- 1 | 6 | 7 |
10 | <%= attribute.human_name %>: 11 | <% if attribute.attachment? -%> 12 | {#if <%= singular_table_name %>.<%= attribute.column_name %>} 13 | .<%= attribute.column_name %>.url}> 14 | {<%= singular_table_name %>.<%= attribute.column_name %>.filename} 15 | 16 | {/if} 17 |
18 | <% elsif attribute.attachments? -%> 19 | 20 | {#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }} 21 |
31 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Show.svelte.tt:
--------------------------------------------------------------------------------
1 |
7 |
8 |
16 | {flash.notice} 17 |
18 | {/if} 19 | 20 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte/types.ts.tt:
--------------------------------------------------------------------------------
1 | export interface <%= inertia_model_type %> {
2 | id: number
3 | <% attributes.reject(&:password_digest?).each do |attribute| -%>
4 | <%= attribute.column_name %>: <%= ts_type(attribute) %>
5 | <% end -%>
6 | }
7 |
8 | export type <%= inertia_model_form_type %> = Omit<<%= inertia_model_type %>, <%= omit_input_attributes.map { |a| "'#{a}'" }.join(' | ') %>><% if custom_form_attributes.any? -%> & {
9 | <% custom_form_attributes.map do |attribute| -%>
10 | <% if attribute.password_digest? -%>
11 | password: string
12 | password_confirmation: string
13 | <% elsif attribute.attachment? -%>
14 | <%= attribute.column_name %>?: File
15 | <% elsif attribute.attachments? -%>
16 | <%= attribute.column_name %>?: File[]
17 | <% end -%>
18 | <% end -%>
19 | }<% end %>
20 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Edit.svelte.tt:
--------------------------------------------------------------------------------
1 |
19 |
20 |
46 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Edit.ts.svelte.tt:
--------------------------------------------------------------------------------
1 |
20 |
21 |
47 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Index.svelte.tt:
--------------------------------------------------------------------------------
1 |
8 |
9 |
16 | {flash.notice} 17 |
18 | {/if} 19 | 20 |34 | `} 36 | class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" 37 | > 38 | Show this <%= human_name.downcase %> 39 | 40 |
41 | {/each} 42 |
44 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Index.ts.svelte.tt:
--------------------------------------------------------------------------------
1 |
9 |
10 |
17 | {flash.notice} 18 |
19 | {/if} 20 | 21 |35 | `} 37 | class="ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" 38 | > 39 | Show this <%= human_name.downcase %> 40 | 41 |
42 | {/each} 43 |
45 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/New.svelte.tt:
--------------------------------------------------------------------------------
1 |
13 |
14 |
34 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/New.ts.svelte.tt:
--------------------------------------------------------------------------------
1 |
14 |
15 |
35 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/svelte4/One.svelte.tt: -------------------------------------------------------------------------------- 1 | 4 | 5 |
8 | <%= attribute.human_name %>: 9 | <% if attribute.attachment? -%> 10 | {#if <%= singular_table_name %>.<%= attribute.column_name %>} 11 | .<%= attribute.column_name %>.url}> 12 | {<%= singular_table_name %>.<%= attribute.column_name %>.filename} 13 | 14 | {/if} 15 |
16 | <% elsif attribute.attachments? -%> 17 | 18 | {#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }} 19 |29 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/svelte4/One.ts.svelte.tt: -------------------------------------------------------------------------------- 1 | 6 | 7 |
10 | <%= attribute.human_name %>: 11 | <% if attribute.attachment? -%> 12 | {#if <%= singular_table_name %>.<%= attribute.column_name %>} 13 | .<%= attribute.column_name %>.url}> 14 | {<%= singular_table_name %>.<%= attribute.column_name %>.filename} 15 | 16 | {/if} 17 |
18 | <% elsif attribute.attachments? -%> 19 | 20 | {#each <%= singular_table_name %>.<%= attribute.column_name %> as { url, filename }} 21 |
31 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Show.svelte.tt:
--------------------------------------------------------------------------------
1 |
8 |
9 |
17 | {flash.notice} 18 |
19 | {/if} 20 | 21 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/svelte4/Show.ts.svelte.tt:
--------------------------------------------------------------------------------
1 |
9 |
10 |
18 | {flash.notice} 19 |
20 | {/if} 21 | 22 |49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/svelte4/types.ts.tt: -------------------------------------------------------------------------------- 1 | export interface <%= inertia_model_type %> { 2 | id: number 3 | <% attributes.reject(&:password_digest?).each do |attribute| -%> 4 | <%= attribute.column_name %>: <%= ts_type(attribute) %> 5 | <% end -%> 6 | } 7 | 8 | export type <%= inertia_model_form_type %> = Omit<<%= inertia_model_type %>, <%= omit_input_attributes.map { |a| "'#{a}'" }.join(' | ') %>><% if custom_form_attributes.any? -%> & { 9 | <% custom_form_attributes.map do |attribute| -%> 10 | <% if attribute.password_digest? -%> 11 | password: string 12 | password_confirmation: string 13 | <% elsif attribute.attachment? -%> 14 | <%= attribute.column_name %>?: File 15 | <% elsif attribute.attachments? -%> 16 | <%= attribute.column_name %>?: File[] 17 | <% end -%> 18 | <% end -%> 19 | }<% end %> 20 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.ts.vue.tt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
26 | 27 | 28 | 46 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.vue.tt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
26 | 27 | 28 | 45 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.ts.vue.tt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
9 | {{ flash.notice }} 10 |
11 | 12 |26 | 30 | Show this <%= human_name.downcase %> 31 | 32 |
33 | 34 |36 | 37 | 38 | 48 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.vue.tt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
9 | {{ flash.notice }} 10 |
11 | 12 |26 | 30 | Show this <%= human_name.downcase %> 31 | 32 |
33 | 34 |36 | 37 | 38 | 44 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/vue/New.ts.vue.tt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
20 | 21 | 22 | 34 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/vue/New.vue.tt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
20 |
21 |
22 |
33 |
--------------------------------------------------------------------------------
/lib/generators/inertia_tw_templates/scaffold/templates/vue/One.ts.vue.tt:
--------------------------------------------------------------------------------
1 |
2 |
5 | <%= attribute.human_name %>:
6 | <% if attribute.attachment? -%>
7 |
8 | {{ <%= singular_table_name %>.<%= attribute.column_name %>.filename }}
9 |
10 |
5 | <%= attribute.human_name %>:
6 | <% if attribute.attachment? -%>
7 |
8 | {{ <%= singular_table_name %>.<%= attribute.column_name %>.filename }}
9 |
10 |
10 | {{ flash.notice }} 11 |
12 | 13 |42 | 43 | 44 | 50 | -------------------------------------------------------------------------------- /lib/generators/inertia_tw_templates/scaffold/templates/vue/types.ts.tt: -------------------------------------------------------------------------------- 1 | export interface <%= inertia_model_type %> { 2 | id: number 3 | <% attributes.reject(&:password_digest?).each do |attribute| -%> 4 | <%= attribute.column_name %>: <%= ts_type(attribute) %> 5 | <% end -%> 6 | } 7 | 8 | export type <%= inertia_model_form_type %> = Omit<<%= inertia_model_type %>, <%= omit_input_attributes.map { |a| "'#{a}'" }.join(' | ') %>><% if custom_form_attributes.any? -%> & { 9 | <% custom_form_attributes.map do |attribute| -%> 10 | <% if attribute.password_digest? -%> 11 | password: string 12 | password_confirmation: string 13 | <% elsif attribute.attachment? -%> 14 | <%= attribute.column_name %>?: File 15 | <% elsif attribute.attachments? -%> 16 | <%= attribute.column_name %>?: File[] 17 | <% end -%> 18 | <% end -%> 19 | }<% end %> 20 | -------------------------------------------------------------------------------- /lib/inertia_rails.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'inertia_rails/renderer' 4 | require 'inertia_rails/engine' 5 | 6 | require 'patches/debug_exceptions' 7 | require 'patches/better_errors' 8 | require 'patches/request' 9 | require 'patches/mapper' 10 | 11 | ActionController::Renderers.add :inertia do |component, options| 12 | InertiaRails::Renderer.new( 13 | component, 14 | self, 15 | request, 16 | response, 17 | method(:render), 18 | props: options[:props], 19 | view_data: options[:view_data], 20 | deep_merge: options[:deep_merge], 21 | encrypt_history: options[:encrypt_history], 22 | clear_history: options[:clear_history] 23 | ).render 24 | end 25 | 26 | module InertiaRails 27 | class Error < StandardError; end 28 | 29 | def self.deprecator # :nodoc: 30 | @deprecator ||= ActiveSupport::Deprecation.new 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/inertia_rails/action_filter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # 3 | # Based on AbstractController::Callbacks::ActionFilter 4 | # https://github.com/rails/rails/blob/v7.2.0/actionpack/lib/abstract_controller/callbacks.rb#L39 5 | module InertiaRails 6 | class ActionFilter 7 | def initialize(conditional_key, actions) 8 | @conditional_key = conditional_key 9 | @actions = Array(actions).map(&:to_s).to_set 10 | end 11 | 12 | def match?(controller) 13 | missing_action = @actions.find { |action| !controller.available_action?(action) } 14 | if missing_action 15 | message = <<~MSG 16 | The #{missing_action} action could not be found for the :inertia_share 17 | callback on #{controller.class.name}, but it is listed in the controller's 18 | #{@conditional_key.inspect} option. 19 | MSG 20 | 21 | raise AbstractController::ActionNotFound.new(message, controller, missing_action) 22 | end 23 | 24 | @actions.include?(controller.action_name) 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/inertia_rails/always_prop.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRails 4 | class AlwaysProp < BaseProp 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/inertia_rails/base_prop.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRails 4 | # Base class for all props. 5 | class BaseProp 6 | def initialize(&block) 7 | @block = block 8 | end 9 | 10 | def call(controller) 11 | controller.instance_exec(&@block) 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/inertia_rails/defer_prop.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRails 4 | class DeferProp < IgnoreOnFirstLoadProp 5 | DEFAULT_GROUP = 'default' 6 | 7 | attr_reader :group 8 | 9 | def initialize(group: nil, merge: nil, deep_merge: nil, &block) 10 | raise ArgumentError, 'Cannot set both `deep_merge` and `merge` to true' if deep_merge && merge 11 | 12 | super(&block) 13 | 14 | @group = group || DEFAULT_GROUP 15 | @merge = merge || deep_merge 16 | @deep_merge = deep_merge 17 | end 18 | 19 | def merge? 20 | @merge 21 | end 22 | 23 | def deep_merge? 24 | @deep_merge 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/inertia_rails/engine.rb: -------------------------------------------------------------------------------- 1 | require_relative "middleware" 2 | require_relative "controller" 3 | 4 | module InertiaRails 5 | class Engine < ::Rails::Engine 6 | initializer "inertia_rails.configure_rails_initialization" do |app| 7 | app.middleware.use ::InertiaRails::Middleware 8 | end 9 | 10 | initializer "inertia_rails.action_controller" do 11 | ActiveSupport.on_load(:action_controller_base) do 12 | include ::InertiaRails::Controller 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/inertia_rails/generators/scaffold_template_base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'rails/generators/resource_helpers' 4 | require_relative 'controller_template_base' 5 | 6 | module InertiaRails 7 | module Generators 8 | class ScaffoldTemplateBase < ControllerTemplateBase 9 | include Rails::Generators::ResourceHelpers 10 | 11 | remove_argument :actions 12 | 13 | argument :attributes, type: :array, default: [], banner: 'field:type field:type' 14 | 15 | def copy_view_files 16 | available_views.each do |view| 17 | template "#{options.frontend_framework}/#{view}.#{template_extension}", 18 | File.join(base_path, "#{view}.#{extension}") 19 | end 20 | 21 | template "#{options.frontend_framework}/#{partial_name}.#{template_extension}", 22 | File.join(base_path, "#{inertia_component_name}.#{extension}") 23 | 24 | template "#{options.frontend_framework}/types.ts", File.join(base_path, 'types.ts') if typescript? 25 | end 26 | 27 | private 28 | 29 | def template_extension 30 | return extension unless typescript? 31 | return 'tsx' if options.frontend_framework == 'react' 32 | 33 | "ts.#{extension}" 34 | end 35 | 36 | def available_views 37 | %w[Index Edit Show New Form] 38 | end 39 | 40 | def partial_name 41 | 'One' 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/inertia_rails/helper.rb: -------------------------------------------------------------------------------- 1 | require_relative 'inertia_rails' 2 | 3 | module InertiaRails::Helper 4 | def inertia_ssr_head 5 | controller.instance_variable_get("@_inertia_ssr_head") 6 | end 7 | 8 | def inertia_headers 9 | InertiaRails.deprecator.warn( 10 | "`inertia_headers` is deprecated and will be removed in InertiaRails 4.0, use `inertia_ssr_head` instead." 11 | ) 12 | inertia_ssr_head 13 | end 14 | 15 | def inertia_rendering? 16 | controller.instance_variable_get("@_inertia_rendering") 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/inertia_rails/ignore_on_first_load_prop.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRails 4 | class IgnoreOnFirstLoadProp < BaseProp 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/inertia_rails/inertia_rails.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'inertia_rails/base_prop' 4 | require 'inertia_rails/ignore_on_first_load_prop' 5 | require 'inertia_rails/always_prop' 6 | require 'inertia_rails/lazy_prop' 7 | require 'inertia_rails/optional_prop' 8 | require 'inertia_rails/defer_prop' 9 | require 'inertia_rails/merge_prop' 10 | require 'inertia_rails/configuration' 11 | 12 | module InertiaRails 13 | class << self 14 | CONFIGURATION = Configuration.default 15 | 16 | def configure 17 | yield(CONFIGURATION) 18 | end 19 | 20 | def configuration 21 | CONFIGURATION 22 | end 23 | 24 | def lazy(value = nil, &block) 25 | LazyProp.new(value, &block) 26 | end 27 | 28 | def optional(&block) 29 | OptionalProp.new(&block) 30 | end 31 | 32 | def always(&block) 33 | AlwaysProp.new(&block) 34 | end 35 | 36 | def merge(&block) 37 | MergeProp.new(&block) 38 | end 39 | 40 | def deep_merge(&block) 41 | MergeProp.new(deep_merge: true, &block) 42 | end 43 | 44 | def defer(group: nil, merge: nil, deep_merge: nil, &block) 45 | DeferProp.new(group: group, merge: merge, deep_merge: deep_merge, &block) 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/inertia_rails/lazy_prop.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRails 4 | class LazyProp < IgnoreOnFirstLoadProp 5 | def initialize(value = nil, &block) 6 | raise ArgumentError, 'You must provide either a value or a block, not both' if value && block 7 | 8 | InertiaRails.deprecator.warn( 9 | '`lazy` is deprecated and will be removed in InertiaRails 4.0, use `optional` instead.' 10 | ) 11 | 12 | @value = value 13 | @block = block 14 | end 15 | 16 | def call(controller) 17 | value.respond_to?(:call) ? controller.instance_exec(&value) : value 18 | end 19 | 20 | def value 21 | @value.nil? ? @block : @value 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/inertia_rails/merge_prop.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRails 4 | class MergeProp < BaseProp 5 | def initialize(deep_merge: false, &block) 6 | super(&block) 7 | @deep_merge = deep_merge 8 | end 9 | 10 | def merge? 11 | true 12 | end 13 | 14 | def deep_merge? 15 | @deep_merge 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/inertia_rails/optional_prop.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRails 4 | class OptionalProp < IgnoreOnFirstLoadProp 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/inertia_rails/version.rb: -------------------------------------------------------------------------------- 1 | module InertiaRails 2 | VERSION = "3.8.0" 3 | end 4 | -------------------------------------------------------------------------------- /lib/patches/better_errors.rb: -------------------------------------------------------------------------------- 1 | # Patch BetterErrors::Middleware to render HTML for Inertia requests 2 | # 3 | # Original source: 4 | # https://github.com/BetterErrors/better_errors/blob/v2.5.1/lib/better_errors/middleware.rb 5 | # 6 | 7 | module InertiaRails 8 | module InertiaBetterErrors 9 | def text?(env) 10 | return false if env["HTTP_X_INERTIA"] 11 | 12 | super 13 | end 14 | end 15 | end 16 | 17 | if defined?(BetterErrors) 18 | BetterErrors::Middleware.include InertiaRails::InertiaBetterErrors 19 | end 20 | -------------------------------------------------------------------------------- /lib/patches/debug_exceptions.rb: -------------------------------------------------------------------------------- 1 | # Patch ActionDispatch::DebugExceptions to render HTML for Inertia requests 2 | # 3 | # Rails has introduced text rendering for XHR requests with Rails 4.1 and 4 | # changed the implementation in 4.2, 5.0 and 5.1 (unchanged since then). 5 | # 6 | # The original source needs to be patched, so that Inertia requests are 7 | # NOT responded with plain text, but with HTML. 8 | 9 | if defined?(ActionDispatch::DebugExceptions) 10 | if ActionPack.version.to_s >= '5.1' 11 | require 'patches/debug_exceptions/patch-5-1' 12 | elsif ActionPack.version.to_s >= '5.0' 13 | require 'patches/debug_exceptions/patch-5-0' 14 | else 15 | # This gem supports Rails 5 or later 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/patches/debug_exceptions/patch-5-0.rb: -------------------------------------------------------------------------------- 1 | # Patch ActionDispatch::DebugExceptions to render HTML for Inertia requests 2 | # 3 | # Original source: 4 | # https://github.com/rails/rails/blob/5-0-stable/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb 5 | # 6 | 7 | module InertiaRails 8 | module InertiaDebugExceptions 9 | def render_for_default_application(request, wrapper) 10 | template = create_template(request, wrapper) 11 | file = "rescues/#{wrapper.rescue_template}" 12 | 13 | if request.xhr? && !request.headers['X-Inertia'] # <<<< this line is changed only 14 | body = template.render(template: file, layout: false, formats: [:text]) 15 | format = "text/plain" 16 | else 17 | body = template.render(template: file, layout: 'rescues/layout') 18 | format = "text/html" 19 | end 20 | render(wrapper.status_code, body, format) 21 | end 22 | end 23 | end 24 | 25 | if defined?(ActionDispatch::DebugExceptions) 26 | ActionDispatch::DebugExceptions.prepend InertiaRails::InertiaDebugExceptions 27 | end 28 | -------------------------------------------------------------------------------- /lib/patches/debug_exceptions/patch-5-1.rb: -------------------------------------------------------------------------------- 1 | # Patch ActionDispatch::DebugExceptions to render HTML for Inertia requests 2 | # 3 | # Original source (unchanged since Rails 5.1): 4 | # https://github.com/rails/rails/blob/5-1-stable/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb 5 | # https://github.com/rails/rails/blob/5-2-stable/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb 6 | # https://github.com/rails/rails/blob/6-0-stable/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb 7 | # 8 | 9 | module InertiaRails 10 | module InertiaDebugExceptions 11 | def render_for_browser_request(request, wrapper) 12 | template = create_template(request, wrapper) 13 | file = "rescues/#{wrapper.rescue_template}" 14 | 15 | if request.xhr? && !request.headers['X-Inertia'] # <<<< this line is changed only 16 | body = template.render(template: file, layout: false, formats: [:text]) 17 | format = "text/plain" 18 | else 19 | body = template.render(template: file, layout: "rescues/layout") 20 | format = "text/html" 21 | end 22 | 23 | render(wrapper.status_code, body, format) 24 | end 25 | end 26 | end 27 | 28 | if defined?(ActionDispatch::DebugExceptions) 29 | ActionDispatch::DebugExceptions.prepend InertiaRails::InertiaDebugExceptions 30 | end 31 | -------------------------------------------------------------------------------- /lib/patches/mapper.rb: -------------------------------------------------------------------------------- 1 | module InertiaRails 2 | module InertiaMapper 3 | def inertia(*args, **options) 4 | path = args.any? ? args.first : options 5 | route, component = extract_route_and_component(path) 6 | get(route, to: StaticController.action(:static), defaults: { component: component }, **options) 7 | end 8 | 9 | private 10 | 11 | def extract_route_and_component(path) 12 | if path.is_a?(Hash) 13 | path.first 14 | elsif resource_scope? 15 | [path, InertiaRails.configuration.component_path_resolver(path: [@scope[:module], @scope[:controller]].compact.join('/'), action: path)] 16 | elsif @scope[:module].blank? 17 | [path, path] 18 | else 19 | [path, InertiaRails.configuration.component_path_resolver(path: @scope[:module], action: path)] 20 | end 21 | end 22 | end 23 | end 24 | 25 | ActionDispatch::Routing::Mapper.include InertiaRails::InertiaMapper 26 | -------------------------------------------------------------------------------- /lib/patches/request.rb: -------------------------------------------------------------------------------- 1 | module InertiaRails 2 | module InertiaRequest 3 | def inertia? 4 | key? 'HTTP_X_INERTIA' 5 | end 6 | 7 | def inertia_partial? 8 | key?('HTTP_X_INERTIA_PARTIAL_COMPONENT') 9 | end 10 | end 11 | end 12 | 13 | ActionDispatch::Request.include InertiaRails::InertiaRequest 14 | -------------------------------------------------------------------------------- /lib/tasks/inertia_rails.rake: -------------------------------------------------------------------------------- 1 | namespace :inertia_rails do 2 | namespace :install do 3 | desc "Installs inertia_rails packages and configurations for a React based app" 4 | task :react => :environment do 5 | system 'rails g inertia_rails:install --front_end react' 6 | end 7 | desc "Installs inertia_rails packages and configurations for a Vue based app" 8 | task vue: :environment do 9 | system 'rails g inertia_rails:install --front_end vue' 10 | end 11 | desc "Installs inertia_rails packages and configurations for a Svelte based app" 12 | task svelte: :environment do 13 | system 'rails g inertia_rails:install --front_end svelte' 14 | end 15 | end 16 | end -------------------------------------------------------------------------------- /spec/dummy/.ruby-version: -------------------------------------------------------------------------------- 1 | 2.6.3 2 | -------------------------------------------------------------------------------- /spec/dummy/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | def controller_method 3 | 'controller_method value' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inertiajs/inertia-rails/291d0d2f09b8085881b93474879d40d413fa55fc/spec/dummy/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_child_share_test_controller.rb: -------------------------------------------------------------------------------- 1 | class InertiaChildShareTestController < InertiaShareTestController 2 | inertia_share name: 'No Longer Brandon' 3 | 4 | def share_with_inherited 5 | render inertia: 'ShareTestComponent' 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_config_test_controller.rb: -------------------------------------------------------------------------------- 1 | class InertiaConfigTestController < ApplicationController 2 | inertia_config( 3 | deep_merge_shared_data: true, 4 | ssr_enabled: true, 5 | ssr_url: "http://localhost:7777", 6 | layout: "test", 7 | version: "1.0", 8 | encrypt_history: false, 9 | ) 10 | 11 | # Test that modules included in the same class can also call it. 12 | inertia_config( 13 | version: "2.0", 14 | ) 15 | 16 | def configuration 17 | render json: inertia_configuration.send(:options) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_encrypt_history_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class InertiaEncryptHistoryController < ApplicationController 4 | inertia_config( 5 | encrypt_history: -> { action_name != 'default_config' } 6 | ) 7 | 8 | def default_config 9 | render inertia: 'TestComponent' 10 | end 11 | 12 | def encrypt_history 13 | render inertia: 'TestComponent' 14 | end 15 | 16 | def override_config 17 | render inertia: 'TestComponent', encrypt_history: false 18 | end 19 | 20 | def clear_history 21 | render inertia: 'TestComponent', clear_history: true 22 | end 23 | 24 | def clear_history_after_redirect 25 | redirect_to :empty_test, inertia: { clear_history: true } 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_lambda_shared_props_controller.rb: -------------------------------------------------------------------------------- 1 | class InertiaLambdaSharedPropsController < ApplicationController 2 | inertia_share someProperty: -> { 3 | { 4 | property_a: "some value", 5 | property_b: "this value" 6 | } 7 | } 8 | 9 | def lamda_shared_props 10 | render inertia: 'ShareTestComponent', props: { property_c: "some other value" } 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_merge_instance_props_controller.rb: -------------------------------------------------------------------------------- 1 | class InertiaMergeInstancePropsController < ApplicationController 2 | use_inertia_instance_props 3 | inertia_share do 4 | { 5 | nested: { 6 | points: 55, 7 | rebounds: 10, 8 | } 9 | } 10 | end 11 | 12 | def merge_instance_props 13 | @nested = { 14 | points: 100, 15 | } 16 | 17 | render inertia: 'InertiaTestComponent', deep_merge: true 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_merge_shared_controller.rb: -------------------------------------------------------------------------------- 1 | class InertiaMergeSharedController < ApplicationController 2 | inertia_share do 3 | { 4 | nested: { 5 | goals: 100, 6 | assists: 100, 7 | } 8 | } 9 | end 10 | 11 | def merge_shared 12 | render inertia: 'ShareTestComponent', props: { 13 | nested: { 14 | assists: 200, 15 | } 16 | } 17 | end 18 | 19 | def deep_merge_shared 20 | render inertia: 'ShareTestComponent', props: { 21 | nested: { 22 | assists: 300, 23 | } 24 | }, deep_merge: true 25 | end 26 | 27 | def shallow_merge_shared 28 | render inertia: 'ShareTestComponent', props: { 29 | nested: { 30 | assists: 200, 31 | } 32 | }, deep_merge: false 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_multithreaded_share_controller.rb: -------------------------------------------------------------------------------- 1 | class InertiaMultithreadedShareController < ApplicationController 2 | inertia_share name: 'Michael' 3 | inertia_share has_goat_status: true 4 | 5 | def share_multithreaded 6 | sleep 1 7 | render inertia: 'ShareTestComponent' 8 | end 9 | 10 | def share_multithreaded_error 11 | raise Exception 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_rails_mimic_controller.rb: -------------------------------------------------------------------------------- 1 | class InertiaRailsMimicController < ApplicationController 2 | inertia_config( 3 | default_render: -> { action_name == "default_render_test" }, 4 | ) 5 | use_inertia_instance_props 6 | 7 | def instance_props_test 8 | @name = 'Brandon' 9 | @sport = 'hockey' 10 | 11 | render inertia: 'TestComponent' 12 | end 13 | 14 | def default_render_test 15 | @name = 'Brian' 16 | end 17 | 18 | def provided_props_test 19 | @name = 'Brian' 20 | 21 | render inertia: 'TestComponent', props: { 22 | sport: 'basketball', 23 | } 24 | end 25 | 26 | def default_component_test 27 | render inertia: true 28 | end 29 | 30 | def default_component_with_props_test 31 | render inertia: { my: 'props' } 32 | end 33 | 34 | def default_component_with_duplicated_props_test 35 | # should raise an error 36 | render inertia: { my: 'props' }, props: { another: 'prop' } 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_responders_test_controller.rb: -------------------------------------------------------------------------------- 1 | require 'responders' 2 | 3 | class Thing 4 | end 5 | 6 | class InertiaRespondersTestController < ApplicationController 7 | self.responder = ActionController::Responder 8 | respond_to :html 9 | 10 | def redirect_test 11 | respond_with Thing.new, location: '/foo' 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_session_continuity_test_controller.rb: -------------------------------------------------------------------------------- 1 | class InertiaSessionContinuityTestController < ApplicationController 2 | def initialize_session 3 | render inertia: 'TestNewSessionComponent' 4 | end 5 | 6 | def submit_form_to_test_csrf 7 | render inertia: 'TestComponent' 8 | end 9 | 10 | def clear_session 11 | session.clear 12 | 13 | return redirect_to initialize_session_path 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/inertia_share_test_controller.rb: -------------------------------------------------------------------------------- 1 | class InertiaShareTestController < ApplicationController 2 | inertia_share name: 'Brandon' 3 | inertia_share sport: -> { 'hockey' } 4 | inertia_share({a_hash: 'also works'}) 5 | inertia_share do 6 | { 7 | position: 'center', 8 | number: number, 9 | } 10 | end 11 | 12 | def share 13 | render inertia: 'ShareTestComponent' 14 | end 15 | 16 | private 17 | 18 | def number 19 | 29 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/dummy/app/controllers/transformed_inertia_rails_mimic_controller.rb: -------------------------------------------------------------------------------- 1 | class TransformedInertiaRailsMimicController < ApplicationController 2 | inertia_config( 3 | default_render: true, 4 | component_path_resolver: ->(path:, action:) do 5 | "#{path.camelize}/#{action.camelize}" 6 | end 7 | ) 8 | 9 | def render_test 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/dummy/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /spec/dummy/app/javascript/packs/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. JavaScript code in this file should be added after the last require_* statement. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require rails-ujs 14 | //= require_tree . 15 | -------------------------------------------------------------------------------- /spec/dummy/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | <%= inertia_ssr_head %> 2 | <%= yield %> 3 | <%= local_assigns.except(:page, :inertia_ssr_head).to_json.html_safe %> 4 | -------------------------------------------------------------------------------- /spec/dummy/app/views/layouts/conditional.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= yield %> 3 | -------------------------------------------------------------------------------- /spec/dummy/app/views/layouts/testing.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= yield %> 3 | -------------------------------------------------------------------------------- /spec/dummy/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /spec/dummy/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /spec/dummy/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path('..', __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to setup or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at anytime and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # puts "\n== Copying sample files ==" 21 | # unless File.exist?('config/database.yml') 22 | # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' 23 | # end 24 | 25 | puts "\n== Preparing database ==" 26 | system! 'bin/rails db:prepare' 27 | 28 | puts "\n== Removing old logs and tempfiles ==" 29 | system! 'bin/rails log:clear tmp:clear' 30 | 31 | puts "\n== Restarting application server ==" 32 | system! 'bin/rails restart' 33 | end 34 | -------------------------------------------------------------------------------- /spec/dummy/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative 'config/environment' 4 | 5 | run Rails.application 6 | -------------------------------------------------------------------------------- /spec/dummy/config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative 'boot' 2 | 3 | require "rails" 4 | # Pick the frameworks you want: 5 | # require "active_model/railtie" 6 | # require "active_job/railtie" 7 | # require "active_record/railtie" 8 | # require "active_storage/engine" 9 | require "action_controller/railtie" 10 | # require "action_mailer/railtie" 11 | # require "action_mailbox/engine" 12 | # require "action_text/engine" 13 | # require "action_view/railtie" 14 | # require "action_cable/engine" 15 | # require "sprockets/railtie" 16 | # require "rails/test_unit/railtie" 17 | 18 | Bundler.require(*Rails.groups) 19 | require "inertia_rails" 20 | 21 | module Dummy 22 | class Application < Rails::Application 23 | if Gem::Version.new(Rails::VERSION::STRING) >= Gem::Version.new('5.1.0') 24 | # Initialize configuration defaults for current Rails version. 25 | config.load_defaults "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}" 26 | end 27 | 28 | # Settings in config/environments/* take precedence over those specified here. 29 | # Application configuration can go into files in config/initializers 30 | # -- all .rb files in that directory are automatically loaded after loading 31 | # the framework and any gems in your application. 32 | 33 | # Required for Rails 5.0 and 5.1 34 | config.secret_key_base = SecureRandom.hex 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /spec/dummy/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) 3 | 4 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) 5 | $LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) 6 | -------------------------------------------------------------------------------- /spec/dummy/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite. Versions 3.8.0 and up are supported. 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: db/test.sqlite3 22 | 23 | production: 24 | <<: *default 25 | database: db/production.sqlite3 26 | -------------------------------------------------------------------------------- /spec/dummy/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy 4 | # For further information see the following documentation 5 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 6 | 7 | # Rails.application.config.content_security_policy do |policy| 8 | # policy.default_src :self, :https 9 | # policy.font_src :self, :https, :data 10 | # policy.img_src :self, :https, :data 11 | # policy.object_src :none 12 | # policy.script_src :self, :https 13 | # policy.style_src :self, :https 14 | 15 | # # Specify URI for violation reports 16 | # # policy.report_uri "/csp-violation-report-endpoint" 17 | # end 18 | 19 | # If you are using UJS then enable automatic nonce generation 20 | # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } 21 | 22 | # Set the nonce only to specific directives 23 | # Rails.application.config.content_security_policy_nonce_directives = %w(script-src) 24 | 25 | # Report CSP violations to a specified URI 26 | # For further information see the following documentation: 27 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only 28 | # Rails.application.config.content_security_policy_report_only = true 29 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /spec/dummy/config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /spec/dummy/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at https://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | -------------------------------------------------------------------------------- /spec/dummy/config/puma.rb: -------------------------------------------------------------------------------- 1 | # Puma can serve each request in a thread from an internal thread pool. 2 | # The `threads` method setting takes two numbers: a minimum and maximum. 3 | # Any libraries that use thread pools should be configured to match 4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum 5 | # and maximum; this matches the default thread size of Active Record. 6 | # 7 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } 8 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } 9 | threads min_threads_count, max_threads_count 10 | 11 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 12 | # 13 | port ENV.fetch("PORT") { 3000 } 14 | 15 | # Specifies the `environment` that Puma will run in. 16 | # 17 | environment ENV.fetch("RAILS_ENV") { "development" } 18 | 19 | # Specifies the `pidfile` that Puma will use. 20 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } 21 | 22 | # Specifies the number of `workers` to boot in clustered mode. 23 | # Workers are forked web server processes. If using threads and workers together 24 | # the concurrency of the application would be max `threads` * `workers`. 25 | # Workers do not work on JRuby or Windows (both of which do not support 26 | # processes). 27 | # 28 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 } 29 | 30 | # Use the `preload_app!` method when specifying a `workers` number. 31 | # This directive tells Puma to first boot the application and load code 32 | # before forking the application. This takes advantage of Copy On Write 33 | # process behavior so workers use less memory. 34 | # 35 | # preload_app! 36 | 37 | # Allow puma to be restarted by `rails restart` command. 38 | plugin :tmp_restart 39 | -------------------------------------------------------------------------------- /spec/dummy/config/spring.rb: -------------------------------------------------------------------------------- 1 | Spring.watch( 2 | ".ruby-version", 3 | ".rbenv-vars", 4 | "tmp/restart.txt", 5 | "tmp/caching-dev.txt" 6 | ) 7 | -------------------------------------------------------------------------------- /spec/dummy/log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inertiajs/inertia-rails/291d0d2f09b8085881b93474879d40d413fa55fc/spec/dummy/log/.keep -------------------------------------------------------------------------------- /spec/dummy/log/production.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inertiajs/inertia-rails/291d0d2f09b8085881b93474879d40d413fa55fc/spec/dummy/log/production.log -------------------------------------------------------------------------------- /spec/dummy/public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inertiajs/inertia-rails/291d0d2f09b8085881b93474879d40d413fa55fc/spec/dummy/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /spec/dummy/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inertiajs/inertia-rails/291d0d2f09b8085881b93474879d40d413fa55fc/spec/dummy/public/apple-touch-icon.png -------------------------------------------------------------------------------- /spec/dummy/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/inertiajs/inertia-rails/291d0d2f09b8085881b93474879d40d413fa55fc/spec/dummy/public/favicon.ico -------------------------------------------------------------------------------- /spec/fixtures/install_generator/dummy/Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | -------------------------------------------------------------------------------- /spec/fixtures/install_generator/dummy/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | 6 | <%= csrf_meta_tags %> 7 | <%= csp_meta_tag %> 8 | 9 | 10 |