├── .github └── workflows │ └── main.yml ├── .gitignore ├── .rspec ├── .standard.yml ├── CHANGELOG.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── bin ├── console └── setup ├── inertia_rails-contrib.gemspec ├── lib ├── inertia_rails-contrib.rb ├── inertia_rails_contrib.rb └── inertia_rails_contrib │ ├── configuration.rb │ ├── engine.rb │ ├── inertia_ui_modal.rb │ ├── inertia_ui_modal │ ├── inertia_rails_patch.rb │ ├── redirect.rb │ └── renderer.rb │ └── version.rb └── spec ├── integration └── inertiaui_modal_spec.rb ├── internal ├── app │ ├── controllers │ │ └── test_controller.rb │ └── views │ │ └── layouts │ │ └── application.html.erb └── config │ ├── initializers │ └── inertia_rails.rb │ └── routes.rb └── spec_helper.rb /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Ruby 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | pull_request: 9 | 10 | jobs: 11 | lint: 12 | runs-on: ubuntu-latest 13 | name: Linter 14 | env: 15 | BUNDLE_JOBS: 4 16 | BUNDLE_RETRY: 3 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Set up Ruby 20 | uses: ruby/setup-ruby@v1 21 | with: 22 | ruby-version: "3.3" 23 | bundler: latest 24 | bundler-cache: true 25 | - name: Run StandardRB 26 | run: bundle exec standardrb 27 | 28 | build: 29 | runs-on: ubuntu-latest 30 | name: Ruby ${{ matrix.ruby }} 31 | env: 32 | BUNDLE_JOBS: 4 33 | BUNDLE_RETRY: 3 34 | strategy: 35 | matrix: 36 | ruby: 37 | - "3.3" 38 | - "3.2" 39 | - "3.1" 40 | - "3.0" 41 | 42 | steps: 43 | - uses: actions/checkout@v4 44 | - name: Set up Ruby 45 | uses: ruby/setup-ruby@v1 46 | with: 47 | ruby-version: ${{ matrix.ruby }} 48 | bundler-cache: true 49 | bundler: latest 50 | - uses: oven-sh/setup-bun@v2 51 | with: 52 | bun-version: latest 53 | - name: Set Node.js 20.x 54 | uses: actions/setup-node@v3 55 | with: 56 | node-version: 20.x 57 | - name: Install yarn 58 | run: npm install -g yarn 59 | - name: Install pnpm 60 | run: npm install -g pnpm 61 | - name: Run tests 62 | run: bundle exec rspec 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | /pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | 10 | # rspec failure tracking 11 | .rspec_status 12 | 13 | node_modules/ 14 | docs/.vitepress/dist 15 | docs/.vitepress/cache 16 | 17 | Gemfile.lock 18 | log/ 19 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | --require spec_helper 4 | -------------------------------------------------------------------------------- /.standard.yml: -------------------------------------------------------------------------------- 1 | # For available configuration options, see: 2 | # https://github.com/standardrb/standard 3 | ruby_version: 3.0 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog], 6 | and this project adheres to [Semantic Versioning]. 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.5.0] - 2025-06-11 11 | 12 | Added: 13 | 14 | - [InertiaUI Modal](https://github.com/inertiaui/modal) support ([@skryukov]) 15 | 16 | ## [0.4.0] - 2024-12-23 17 | 18 | Changed: 19 | 20 | - Generators are upstreamed to the `inertia_rails` gem ([@skryukov]) 21 | 22 | ## [0.3.0] - 2024-10-25 23 | 24 | Added: 25 | 26 | - [BREAKING] Svelte 5 support ([@skryukov]) 27 | - The `--framework=svelte` option now installs Svelte 5 28 | - New `--framework=svelte4` option installs Svelte 4 29 | - Support for Svelte 5 in the installation generator 30 | - Support for Svelte 5 in the scaffold templates 31 | 32 | ## [0.2.2] - 2024-10-09 33 | 34 | Added: 35 | 36 | - TypeScript support for the installation generator ([@skryukov]) 37 | Note that it doesn't include scaffold templates yet. 38 | 39 | - New `--inertia-version` option for the installation generator ([@skryukov]) 40 | This allows you to specify the Inertia.js version to install. 41 | 42 | - Support `tailwind.config.ts` for Tailwind CSS template guessing ([@Shaglock]) 43 | 44 | Fixed: 45 | 46 | - Correct examples for default layouts in inertia entrypoints ([@skryukov]) 47 | - Inertia attribute added to the head tag in the layout for vue ([@skryukov]) 48 | - Remove duplicate `vite_stylesheet_tag` when Tailwind CSS is installed ([@skryukov]) 49 | 50 | ## [0.2.1] - 2024-08-11 51 | 52 | Added: 53 | 54 | - Support `pnpm` package manager ([@skryukov]) 55 | - New `--verbose` option for the installation generator ([@skryukov]) 56 | 57 | Fixed: 58 | 59 | - Support installation alongside Webpacker ([@skryukov]) 60 | 61 | ## [0.2.0] - 2024-08-10 62 | 63 | Added: 64 | 65 | - Improve installation generator ([@skryukov]) 66 | - option to install Vite Rails gem (`--install-vite`) 67 | - option to install Tailwind CSS (`--install-tailwind`) 68 | - option to install without interactivity (`--no-interaction` & `--framework=react|vue|svelte`) 69 | - option to skip example page generation (`--no-example-page`) 70 | - option to choose package manager (`--package-manager=yarn|npm|bun`) 71 | - generate `bin/dev` 72 | 73 | ## [0.1.1] - 2024-06-17 74 | 75 | ### Fixed: 76 | 77 | - Add a missing bracket to the `React/Edit` template. ([@skryukov]) 78 | 79 | ## [0.1.0] - 2024-06-11 80 | 81 | - Initial release ([@iurev], [@skryukov]) 82 | 83 | [@iurev]: https://github.com/iurev 84 | [@Shaglock]: https://github.com/Shaglock 85 | [@skryukov]: https://github.com/skryukov 86 | 87 | [Unreleased]: https://github.com/skryukov/inertia_rails-contrib/compare/v0.5.0...HEAD 88 | [0.5.0]: https://github.com/skryukov/inertia_rails-contrib/compare/v0.4.0...v0.5.0 89 | [0.4.0]: https://github.com/skryukov/inertia_rails-contrib/compare/v0.3.0...v0.4.0 90 | [0.3.0]: https://github.com/skryukov/inertia_rails-contrib/compare/v0.2.2...v0.3.0 91 | [0.2.2]: https://github.com/skryukov/inertia_rails-contrib/compare/v0.2.1...v0.2.2 92 | [0.2.1]: https://github.com/skryukov/inertia_rails-contrib/compare/v0.2.0...v0.2.1 93 | [0.2.0]: https://github.com/skryukov/inertia_rails-contrib/compare/v0.1.1...v0.2.0 94 | [0.1.1]: https://github.com/skryukov/inertia_rails-contrib/compare/v0.1.0...v0.1.1 95 | [0.1.0]: https://github.com/skryukov/inertia_rails-contrib/commits/v0.1.0 96 | 97 | [Keep a Changelog]: https://keepachangelog.com/en/1.0.0/ 98 | [Semantic Versioning]: https://semver.org/spec/v2.0.0.html 99 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # Specify your gem's dependencies in inertia_rails-contrib.gemspec 6 | gemspec 7 | 8 | gem "rake", "~> 13.0" 9 | 10 | gem "rspec", "~> 3.0" 11 | 12 | gem "standard", "~> 1.3" 13 | 14 | gem "rails" 15 | 16 | gem "rspec-rails" 17 | 18 | gem "combustion" 19 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2024 Svyatoslav Kryukov 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # InertiaRailsContrib 2 | 3 | > Community documentation and generators has been upstreamed to the [Inertia Rails repository](https://github.com/inertiajs/inertia-rails). 4 | > 5 | > Please visit the official Inertia Rails documentation at https://inertia-rails.dev. 6 | 7 | From now on we're planning to use `InertiaRailsContrib` as a playground for new features and ideas. 8 | The gem will be updated with new features and improvements, and then the most successful ones will be proposed to the core Inertia Rails repository. 9 | 10 | Future plans: 11 | - Ruby LSP plugin for Inertia Rails 12 | - Modals support 13 | 14 | Stay tuned! 15 | 16 | 17 | Built by Evil Martians 18 | 19 | 20 | ## Installation 21 | 22 | Install the gem and add to the application's Gemfile by executing: 23 | 24 | $ bundle add inertia_rails-contrib 25 | 26 | If bundler is not being used to manage dependencies, install the gem by executing: 27 | 28 | $ gem install inertia_rails-contrib 29 | 30 | ## InertiaUI Modal Support 31 | 32 | `InertiaRailsContrib` provides support for [InertiaUI Modal](https://github.com/inertiaui/modal) in the Rails application. 33 | 34 | With InertiaUI Modal, you can easily open any route in a Modal or Slideover without having to change anything about your existing routes or controllers. 35 | 36 | By default, InertiaUI Modal doesn't require anything from the Inertia Server Adapters, since it just opens modals without changing the URL. 37 | However, InertiaUI Modal also supports updating the URL when opening a modal (see the docs on why you might want that: https://inertiaui.com/inertia-modal/docs/base-route-url). 38 | 39 | ### Setup 40 | 41 | 1. Follow the NPM installation instructions from the [InertiaUI Modal documentation](https://inertiaui.com/inertia-modal/docs/installation#npm-installation). 42 | 43 | 2. Enable InertiaUI Modal, turn on the `enable_inertia_ui_modal` option in the `inertia_rails_contrib.rb` initializer: 44 | 45 | ```ruby 46 | InertiaRailsContrib.configure do |config| 47 | config.enable_inertia_ui_modal = true 48 | end 49 | ``` 50 | 51 | This will add a new render method `inertia_modal` that can be used in the controller actions: 52 | 53 | ```ruby 54 | class PostsController < ApplicationController 55 | def new 56 | render inertia_modal: 'Post/New', props: { post: Post.new }, base_url: posts_path 57 | end 58 | end 59 | ``` 60 | 61 | ## Development 62 | 63 | After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. 64 | 65 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org). 66 | 67 | ## Contributing 68 | 69 | Bug reports and pull requests are welcome on GitHub at https://github.com/skryukov/inertia_rails-contrib. 70 | 71 | ## License 72 | 73 | The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). 74 | -------------------------------------------------------------------------------- /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 "standard/rake" 9 | 10 | task default: %i[spec standard] 11 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "bundler/setup" 5 | require "inertia_rails-contrib" 6 | 7 | # You can add fixtures and/or initialization code here to make experimenting 8 | # with your gem easier. You can also use a different console, if you like. 9 | 10 | require "irb" 11 | IRB.start(__FILE__) 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /inertia_rails-contrib.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "lib/inertia_rails_contrib/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "inertia_rails-contrib" 7 | spec.version = InertiaRailsContrib::VERSION 8 | spec.authors = ["Svyatoslav Kryukov"] 9 | spec.email = ["me@skryukov.dev"] 10 | 11 | spec.summary = "A collection of extensions and developer tools for Rails Inertia adapter" 12 | spec.description = "A collection of extensions and developer tools for Rails Inertia adapter" 13 | spec.homepage = "https://github.com/skryukov/inertia_rails-contrib" 14 | spec.license = "MIT" 15 | spec.required_ruby_version = ">= 2.7.0" 16 | 17 | spec.metadata = { 18 | "bug_tracker_uri" => "#{spec.homepage}/issues", 19 | "changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md", 20 | "documentation_uri" => "#{spec.homepage}/blob/main/README.md", 21 | "homepage_uri" => spec.homepage, 22 | "source_code_uri" => spec.homepage, 23 | "rubygems_mfa_required" => "true" 24 | } 25 | 26 | spec.files = Dir["{app,lib}/**/*", "CHANGELOG.md", "LICENSE.txt", "README.md"] 27 | spec.require_paths = ["lib"] 28 | 29 | spec.add_dependency "inertia_rails", ">= 3.5.0" 30 | end 31 | -------------------------------------------------------------------------------- /lib/inertia_rails-contrib.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "inertia_rails_contrib" 4 | -------------------------------------------------------------------------------- /lib/inertia_rails_contrib.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if defined?(Rails) 4 | require "inertia_rails" 5 | require_relative "inertia_rails_contrib/engine" 6 | end 7 | 8 | require_relative "inertia_rails_contrib/version" 9 | require_relative "inertia_rails_contrib/configuration" 10 | 11 | module InertiaRailsContrib 12 | class << self 13 | def configuration 14 | @configuration ||= Configuration.new 15 | end 16 | 17 | def configure 18 | yield(configuration) 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/inertia_rails_contrib/configuration.rb: -------------------------------------------------------------------------------- 1 | # lib/inertia_rails_contrib/engine.rb 2 | module InertiaRailsContrib 3 | class Configuration 4 | attr_accessor :enable_inertia_ui_modal 5 | 6 | def initialize 7 | @enable_inertia_ui_modal = false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/inertia_rails_contrib/engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRailsContrib 4 | class Engine < ::Rails::Engine 5 | initializer "inertia_rails_contrib.inertia_ui_modal" do 6 | require_relative "inertia_ui_modal" if InertiaRailsContrib.configuration.enable_inertia_ui_modal 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/inertia_rails_contrib/inertia_ui_modal.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "inertia_ui_modal/renderer" 4 | require_relative "inertia_ui_modal/redirect" 5 | require_relative "inertia_ui_modal/inertia_rails_patch" 6 | 7 | module InertiaRailsContrib 8 | module InertiaUIModal 9 | HEADER_BASE_URL = "X-InertiaUI-Modal-Base-Url" 10 | HEADER_USE_ROUTER = "X-InertiaUI-Modal-Use-Router" 11 | end 12 | end 13 | 14 | ActionController::Renderers.add :inertia_modal do |component, options| 15 | InertiaRailsContrib::InertiaUIModal::Renderer.new( 16 | component, 17 | self, 18 | request, 19 | response, 20 | method(:render), 21 | **options 22 | ).render 23 | end 24 | 25 | ActiveSupport.on_load(:action_controller_base) do 26 | prepend ::InertiaRailsContrib::InertiaUIModal::Redirect 27 | end 28 | -------------------------------------------------------------------------------- /lib/inertia_rails_contrib/inertia_ui_modal/inertia_rails_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "inertia_rails/renderer" 4 | 5 | module InertiaRailsContrib 6 | module InertiaUIModal 7 | module RendererPatch 8 | def page 9 | super.tap do |modal| 10 | if @request.env[:_inertiaui_modal] 11 | modal[:props][:_inertiaui_modal] = @request.env[:_inertiaui_modal] 12 | modal[:url] = modal[:props][:_inertiaui_modal][:url] 13 | end 14 | end 15 | end 16 | end 17 | end 18 | end 19 | 20 | InertiaRails::Renderer.prepend(InertiaRailsContrib::InertiaUIModal::RendererPatch) 21 | -------------------------------------------------------------------------------- /lib/inertia_rails_contrib/inertia_ui_modal/redirect.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRailsContrib 4 | module InertiaUIModal 5 | module Redirect 6 | def redirect_back_or_to(fallback_location, allow_other_host: _allow_other_host, **options) 7 | inertia_modal_referer = request.headers[HEADER_BASE_URL] 8 | if inertia_modal_referer && (allow_other_host || _url_host_allowed?(inertia_modal_referer)) 9 | redirect_to inertia_modal_referer, allow_other_host: allow_other_host, **options 10 | else 11 | super 12 | end 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/inertia_rails_contrib/inertia_ui_modal/renderer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRailsContrib 4 | module InertiaUIModal 5 | class Renderer 6 | KNOWN_KEYWORDS = %i[props view_data deep_merge encrypt_history clear_history].freeze 7 | 8 | def initialize(component, controller, request, response, render_method, base_url: nil, **options) 9 | @request = request 10 | @response = response 11 | @base_url = base_url 12 | @inertia_renderer = InertiaRails::Renderer.new(component, controller, request, response, render_method, **options.slice(*KNOWN_KEYWORDS)) 13 | end 14 | 15 | def render 16 | if @request.headers[HEADER_USE_ROUTER] == "0" || base_url.blank? 17 | return @inertia_renderer.render 18 | end 19 | 20 | page = @inertia_renderer.page 21 | page[:baseUrl] = base_url 22 | page[:meta] = { 23 | deferredProps: page.delete(:deferredProps), 24 | mergeProps: page.delete(:mergeProps) 25 | } 26 | 27 | @request.env[:_inertiaui_modal] = page 28 | 29 | render_base_url 30 | end 31 | 32 | def base_url 33 | @request.headers[HEADER_BASE_URL] || @base_url 34 | end 35 | 36 | def render_base_url 37 | original_env = Rack::MockRequest.env_for( 38 | base_url, 39 | method: @request.method, 40 | params: @request.params 41 | ) 42 | @request.each_header do |k, v| 43 | original_env[k] ||= v 44 | end 45 | 46 | original_request = ActionDispatch::Request.new(original_env) 47 | 48 | path = ActionDispatch::Journey::Router::Utils.normalize_path(original_request.path_info) 49 | Rails.application.routes.recognize_path_with_request(original_request, path, {}) 50 | controller = original_request.controller_class.new 51 | controller.request = @request 52 | controller.response = @response 53 | controller.process(original_request.path_parameters[:action]) 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/inertia_rails_contrib/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module InertiaRailsContrib 4 | VERSION = "0.5.0" 5 | end 6 | -------------------------------------------------------------------------------- /spec/integration/inertiaui_modal_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "spec_helper" 4 | 5 | RSpec.describe "InertiaUI Modal Integration", type: :request do 6 | describe "GET /modal" do 7 | let(:expected_modal) do 8 | { 9 | component: "modal", 10 | props: {hello: "modal"}, 11 | url: "/modal", 12 | version: "1", 13 | encryptHistory: false, 14 | clearHistory: false, 15 | baseUrl: "/base", 16 | meta: { 17 | deferredProps: { 18 | default: ["deferred_param"], 19 | custom: ["merge_param"] 20 | }, 21 | mergeProps: ["merge_param"] 22 | } 23 | } 24 | end 25 | 26 | let(:expected_page) do 27 | { 28 | component: "base", 29 | props: { 30 | base: "prop", 31 | _inertiaui_modal: expected_modal 32 | }, 33 | url: "/modal", 34 | version: "1", 35 | encryptHistory: false, 36 | clearHistory: false 37 | } 38 | end 39 | 40 | let(:expected_defer_modal) do 41 | { 42 | component: "modal", 43 | props: {deferred_param: "deferred"}, 44 | mergeProps: ["merge_param"], 45 | url: "/modal", 46 | version: "1", 47 | encryptHistory: false, 48 | clearHistory: false 49 | } 50 | end 51 | 52 | it "returns page data with base & modal merged together" do 53 | get "/modal" 54 | 55 | expect(response.status).to eq(200) 56 | expect(page_data).to eq(expected_page.as_json) 57 | end 58 | 59 | it "returns base & modal merged together when requested with X-Inertia: true header" do 60 | get "/modal", headers: { 61 | "X-Inertia" => "true", 62 | "X-Inertia-Version" => "1" 63 | } 64 | 65 | expect(response.status).to eq(200) 66 | expect(response.parsed_body).to eq(expected_page.as_json) 67 | end 68 | 69 | it "returns only deferred props when requested" do 70 | get "/modal", headers: { 71 | "X-Inertia" => "true", 72 | "X-Inertia-Version" => "1", 73 | "X-InertiaUI-Modal-Use-Router" => "0", 74 | "X-Inertia-Partial-Component" => "modal", 75 | "X-Inertia-Partial-Data" => "deferred_param" 76 | } 77 | 78 | expect(response.status).to eq(200) 79 | expect(response.parsed_body).to eq(expected_defer_modal.as_json) 80 | end 81 | 82 | def page_data 83 | doc = Nokogiri::HTML(response.body) 84 | data_page = doc.at_css("#app")&.[]("data-page") 85 | return nil unless data_page 86 | 87 | JSON.parse(CGI.unescapeHTML(data_page)) 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /spec/internal/app/controllers/test_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TestController < ActionController::Base 4 | layout "application" 5 | 6 | def base 7 | render inertia: "base", props: {base: "prop"} 8 | end 9 | 10 | def modal 11 | render inertia_modal: "modal", props: { 12 | hello: "modal", 13 | optional_param: InertiaRails.optional { "optional" }, 14 | deferred_param: InertiaRails.defer { "deferred" }, 15 | merge_param: InertiaRails.defer(group: "custom", merge: true) { {additional: "data"} } 16 | }, base_url: "/base" 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /spec/internal/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /spec/internal/config/initializers/inertia_rails.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | InertiaRails.configure do |config| 4 | config.version = "1" 5 | end 6 | 7 | InertiaRailsContrib.configure do |config| 8 | config.enable_inertia_ui_modal = true 9 | end 10 | -------------------------------------------------------------------------------- /spec/internal/config/routes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Rails.application.routes.draw do 4 | get "/base", to: "test#base" 5 | get "/modal", to: "test#modal" 6 | end 7 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "bundler/setup" 4 | require "combustion" 5 | 6 | Combustion.initialize! :action_controller do 7 | config.hosts.clear 8 | config.secret_key_base = "test_secret" 9 | config.cache_classes = true 10 | config.eager_load = false 11 | end 12 | 13 | require "inertia_rails-contrib" 14 | require "rspec/rails" 15 | 16 | RSpec.configure do |config| 17 | config.use_transactional_fixtures = true 18 | 19 | def app 20 | Rails.application 21 | end 22 | end 23 | --------------------------------------------------------------------------------