inertia_rails-contrib 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +21 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +187 -0
  5. data/lib/generators/inertia/controller/controller_generator.rb +16 -0
  6. data/lib/generators/inertia/controller/templates/controller.rb.tt +10 -0
  7. data/lib/generators/inertia/install/install_generator.rb +151 -0
  8. data/lib/generators/inertia/install/templates/assets/inertia.svg +1 -0
  9. data/lib/generators/inertia/install/templates/assets/react.svg +1 -0
  10. data/lib/generators/inertia/install/templates/assets/svelte.svg +1 -0
  11. data/lib/generators/inertia/install/templates/assets/vite_ruby.svg +1 -0
  12. data/lib/generators/inertia/install/templates/assets/vue.svg +1 -0
  13. data/lib/generators/inertia/install/templates/controller.rb +7 -0
  14. data/lib/generators/inertia/install/templates/initializer.rb +4 -0
  15. data/lib/generators/inertia/install/templates/react/InertiaExample.jsx +60 -0
  16. data/lib/generators/inertia/install/templates/react/InertiaExample.module.css +80 -0
  17. data/lib/generators/inertia/install/templates/react/inertia.js +34 -0
  18. data/lib/generators/inertia/install/templates/svelte/InertiaExample.svelte +116 -0
  19. data/lib/generators/inertia/install/templates/svelte/inertia.js +30 -0
  20. data/lib/generators/inertia/install/templates/svelte/svelte.config.js +7 -0
  21. data/lib/generators/inertia/install/templates/vue/InertiaExample.vue +117 -0
  22. data/lib/generators/inertia/install/templates/vue/inertia.js +33 -0
  23. data/lib/generators/inertia/scaffold/scaffold_generator.rb +16 -0
  24. data/lib/generators/inertia/scaffold_controller/scaffold_controller_generator.rb +56 -0
  25. data/lib/generators/inertia/scaffold_controller/templates/controller.rb.tt +102 -0
  26. data/lib/generators/inertia_templates/controller/controller_generator.rb +12 -0
  27. data/lib/generators/inertia_templates/controller/templates/react/view.jsx.tt +8 -0
  28. data/lib/generators/inertia_templates/controller/templates/svelte/view.svelte.tt +2 -0
  29. data/lib/generators/inertia_templates/controller/templates/vue/view.vue.tt +4 -0
  30. data/lib/generators/inertia_templates/scaffold/scaffold_generator.rb +12 -0
  31. data/lib/generators/inertia_templates/scaffold/templates/react/Edit.jsx.tt +36 -0
  32. data/lib/generators/inertia_templates/scaffold/templates/react/Form.jsx.tt +111 -0
  33. data/lib/generators/inertia_templates/scaffold/templates/react/Index.jsx.tt +26 -0
  34. data/lib/generators/inertia_templates/scaffold/templates/react/New.jsx.tt +27 -0
  35. data/lib/generators/inertia_templates/scaffold/templates/react/One.jsx.tt +26 -0
  36. data/lib/generators/inertia_templates/scaffold/templates/react/Show.jsx.tt +39 -0
  37. data/lib/generators/inertia_templates/scaffold/templates/svelte/Edit.svelte.tt +37 -0
  38. data/lib/generators/inertia_templates/scaffold/templates/svelte/Form.svelte.tt +96 -0
  39. data/lib/generators/inertia_templates/scaffold/templates/svelte/Index.svelte.tt +42 -0
  40. data/lib/generators/inertia_templates/scaffold/templates/svelte/New.svelte.tt +30 -0
  41. data/lib/generators/inertia_templates/scaffold/templates/svelte/One.svelte.tt +28 -0
  42. data/lib/generators/inertia_templates/scaffold/templates/svelte/Show.svelte.tt +46 -0
  43. data/lib/generators/inertia_templates/scaffold/templates/vue/Edit.vue.tt +36 -0
  44. data/lib/generators/inertia_templates/scaffold/templates/vue/Form.vue.tt +94 -0
  45. data/lib/generators/inertia_templates/scaffold/templates/vue/Index.vue.tt +31 -0
  46. data/lib/generators/inertia_templates/scaffold/templates/vue/New.vue.tt +29 -0
  47. data/lib/generators/inertia_templates/scaffold/templates/vue/One.vue.tt +26 -0
  48. data/lib/generators/inertia_templates/scaffold/templates/vue/Show.vue.tt +44 -0
  49. data/lib/generators/inertia_tw_templates/controller/controller_generator.rb +12 -0
  50. data/lib/generators/inertia_tw_templates/controller/templates/react/view.jsx.tt +8 -0
  51. data/lib/generators/inertia_tw_templates/controller/templates/svelte/view.svelte.tt +2 -0
  52. data/lib/generators/inertia_tw_templates/controller/templates/vue/view.vue.tt +4 -0
  53. data/lib/generators/inertia_tw_templates/scaffold/scaffold_generator.rb +12 -0
  54. data/lib/generators/inertia_tw_templates/scaffold/templates/react/Edit.jsx.tt +43 -0
  55. data/lib/generators/inertia_tw_templates/scaffold/templates/react/Form.jsx.tt +122 -0
  56. data/lib/generators/inertia_tw_templates/scaffold/templates/react/Index.jsx.tt +43 -0
  57. data/lib/generators/inertia_tw_templates/scaffold/templates/react/New.jsx.tt +30 -0
  58. data/lib/generators/inertia_tw_templates/scaffold/templates/react/One.jsx.tt +26 -0
  59. data/lib/generators/inertia_tw_templates/scaffold/templates/react/Show.jsx.tt +54 -0
  60. data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Edit.svelte.tt +45 -0
  61. data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Form.svelte.tt +120 -0
  62. data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Index.svelte.tt +49 -0
  63. data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/New.svelte.tt +33 -0
  64. data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/One.svelte.tt +28 -0
  65. data/lib/generators/inertia_tw_templates/scaffold/templates/svelte/Show.svelte.tt +58 -0
  66. data/lib/generators/inertia_tw_templates/scaffold/templates/vue/Edit.vue.tt +44 -0
  67. data/lib/generators/inertia_tw_templates/scaffold/templates/vue/Form.vue.tt +127 -0
  68. data/lib/generators/inertia_tw_templates/scaffold/templates/vue/Index.vue.tt +43 -0
  69. data/lib/generators/inertia_tw_templates/scaffold/templates/vue/New.vue.tt +32 -0
  70. data/lib/generators/inertia_tw_templates/scaffold/templates/vue/One.vue.tt +26 -0
  71. data/lib/generators/inertia_tw_templates/scaffold/templates/vue/Show.vue.tt +56 -0
  72. data/lib/inertia_rails-contrib.rb +3 -0
  73. data/lib/inertia_rails_contrib/generators/controller_template_base.rb +52 -0
  74. data/lib/inertia_rails_contrib/generators/scaffold_template_base.rb +35 -0
  75. data/lib/inertia_rails_contrib/generators_helper.rb +88 -0
  76. data/lib/inertia_rails_contrib/version.rb +5 -0
  77. data/lib/inertia_rails_contrib.rb +8 -0
  78. metadata +153 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fb44326fd223ef6e631746a499a84dff76d261304651eda8d819fe23decc8857
4
+ data.tar.gz: f9975ec1f185d40f88b34861d4104d0161daa8e070c39d2b60be4bcf75b61aa1
5
+ SHA512:
6
+ metadata.gz: aa516f52b025be207b951b61e4f081607cd6c2b3202cb689ae7378d650f5001008667c55ef4d1e84d869fa9fb23c0403532b429f35eea3a10ffdd80c9226c7b5
7
+ data.tar.gz: e303ce54040f9d6268037210c7fe7f51929514900d22c7550b53fb0fb8264abab9cf0ac4c141e30c14bd005b261133268c15967ace013a1bf3b56bd25f24fa2c
data/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
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.1.0] - 2024-06-11
11
+
12
+ - Initial release ([@iurev], [@skryukov])
13
+
14
+ [@iurev]: https://github.com/iurev
15
+ [@skryukov]: https://github.com/skryukov
16
+
17
+ [Unreleased]: https://github.com/skryukov/inertia_rails-contrib/compare/v0.1.0...HEAD
18
+ [0.1.0]: https://github.com/skryukov/inertia_rails-contrib/commits/v0.1.0
19
+
20
+ [Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
21
+ [Semantic Versioning]: https://semver.org/spec/v2.0.0.html
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
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.
data/README.md ADDED
@@ -0,0 +1,187 @@
1
+ # InertiaRailsContrib
2
+
3
+ A collection of extensions, developer tools, and the [community documentation](https://inertia-rails.netlify.app) for [Inertia's Rails adapter](https://github.com/inertiajs/inertia-rails).
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ $ bundle add inertia_rails-contrib
10
+
11
+ If bundler is not being used to manage dependencies, install the gem by executing:
12
+
13
+ $ gem install inertia_rails-contrib
14
+
15
+ ## Usage
16
+
17
+ ### Installation generator
18
+
19
+ `InertiaRailsContrib` comes with a generator that installs and sets up Inertia in a Rails application. **It requires the [Vite Ruby](https://vite-ruby.netlify.app) gem to be installed and configured in the application.**
20
+
21
+ <details>
22
+ <summary>Creating a new Rails application and configuring Vite</summary>
23
+
24
+ This is actually a simple process. First, create a new Rails application:
25
+ ```bash
26
+ rails new myapp --skip-js
27
+ ```
28
+
29
+ Next, install the Vite Ruby gem:
30
+
31
+ ```bash
32
+ bundle add vite_ruby
33
+ bundle exec vite install
34
+ ```
35
+
36
+ If you use macOS, you may need to edit the `config/vite.rb` file to add the following line:
37
+
38
+ ```json
39
+ {
40
+ "development": {
41
+ + "host": "127.0.0.1",
42
+ "autoBuild": true,
43
+ "publicOutputDir": "vite-dev",
44
+ "port": 3036
45
+ }
46
+ }
47
+ ```
48
+
49
+ That's it! Vite is now installed and configured in the Rails application. For more information, refer to the [Vite Ruby documentation](https://vite-ruby.netlify.app) and the [Vite-lizing Rails: get live reload and hot replacement with Vite Ruby](https://evilmartians.com/chronicles/vite-lizing-rails-get-live-reload-and-hot-replacement-with-vite-ruby) article.
50
+
51
+ The next step is to install Inertia!
52
+ </details>
53
+
54
+ To install and setup Inertia in a Rails application, execute the following command in the terminal:
55
+
56
+ ```bash
57
+ bundle add inertia_rails-contrib
58
+ bin/rails generate inertia:install
59
+ ```
60
+
61
+ This command will ask you for the frontend framework you are using (React, Vue, or Svelte) and will install the necessary dependencies and set up the application to work with Inertia.
62
+
63
+ Example output:
64
+
65
+ ```bash
66
+ $ bin/rails generate inertia:install
67
+
68
+ Installing Inertia's Rails adapter
69
+ Adding Inertia's Rails adapter initializer
70
+ create config/initializers/inertia_rails.rb
71
+ Installing Inertia npm packages
72
+ What framework do you want to use with Turbo Mount? [react, vue, svelte] (react)
73
+ run npm add @inertiajs/inertia @inertiajs/react react react-dom from "."
74
+
75
+ added 6 packages, removed 42 packages, and audited 69 packages in 8s
76
+
77
+ 18 packages are looking for funding
78
+ run `npm fund` for details
79
+
80
+ 2 moderate severity vulnerabilities
81
+
82
+ Some issues need review, and may require choosing
83
+ a different dependency.
84
+
85
+ Run `npm audit` for details.
86
+ run npm add --save-dev @vitejs/plugin-react from "."
87
+
88
+ added 58 packages, and audited 127 packages in 6s
89
+
90
+ 22 packages are looking for funding
91
+ run `npm fund` for details
92
+
93
+ 2 moderate severity vulnerabilities
94
+
95
+ Some issues need review, and may require choosing
96
+ a different dependency.
97
+
98
+ Run `npm audit` for details.
99
+ Adding Vite plugin for react
100
+ insert vite.config.ts
101
+ prepend vite.config.ts
102
+ Add "type": "module", to the package.json file
103
+ gsub package.json
104
+ Copying inertia.js into Vite entrypoints
105
+ create app/frontend/entrypoints/inertia.js
106
+ Adding inertia.js script tag to the application layout
107
+ insert app/views/layouts/application.html.erb
108
+ Adding Vite React Refresh tag to the application layout
109
+ insert app/views/layouts/application.html.erb
110
+ Copying example Inertia controller
111
+ create app/controllers/inertia_example_controller.rb
112
+ Adding a route for the example Inertia controller
113
+ route get 'inertia-example', to: 'inertia_example#index'
114
+ Copying framework related files
115
+ create app/frontend/pages/InertiaExample.jsx
116
+ Inertia's Rails adapter successfully installed
117
+ ```
118
+
119
+ With that done, you can now start the Rails server and the Vite development server (we recommend using [Overmind](https://github.com/DarthSim/overmind)):
120
+
121
+ ```bash
122
+ overmind start -f Procfile.dev
123
+ # or
124
+ foreman start -f Procfile.dev
125
+ ```
126
+
127
+ And navigate to `http://127.0.0.1:5100/inertia-example` to see the example Inertia page.
128
+
129
+ ### Scaffold generator
130
+
131
+ `InertiaRailsContrib` also comes with a scaffold generator that generates a scaffold for a model with Inertia. To use it, execute the following command in the terminal:
132
+
133
+ ```bash
134
+ bin/rails generate inertia:scaffold ModelName field1:type field2:type
135
+ ```
136
+
137
+ Example output:
138
+
139
+ ```bash
140
+ $ bin/rails generate inertia:scaffold Post title:string body:text
141
+ invoke active_record
142
+ create db/migrate/20240611123952_create_posts.rb
143
+ create app/models/post.rb
144
+ invoke test_unit
145
+ create test/models/post_test.rb
146
+ create test/fixtures/posts.yml
147
+ invoke resource_route
148
+ route resources :posts
149
+ invoke scaffold_controller
150
+ create app/controllers/posts_controller.rb
151
+ invoke inertia_templates
152
+ create app/frontend/pages/Post
153
+ create app/frontend/pages/Post/Index.svelte
154
+ create app/frontend/pages/Post/Edit.svelte
155
+ create app/frontend/pages/Post/Show.svelte
156
+ create app/frontend/pages/Post/New.svelte
157
+ create app/frontend/pages/Post/Form.svelte
158
+ create app/frontend/pages/Post/Post.svelte
159
+ invoke resource_route
160
+ invoke test_unit
161
+ create test/controllers/posts_controller_test.rb
162
+ create test/system/posts_test.rb
163
+ invoke helper
164
+ create app/helpers/posts_helper.rb
165
+ invoke test_unit
166
+ ```
167
+
168
+ #### Tailwind CSS integration
169
+
170
+ `InertiaRailsContrib` tries to detect the presence of Tailwind CSS in the application and generate the templates accordingly. If you want to specify templates type, use the `--inertia-templates` option:
171
+
172
+ - `inertia_templates` - default
173
+ - `inertia_tw_templates` - Tailwind CSS
174
+
175
+ ## Development
176
+
177
+ 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.
178
+
179
+ 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).
180
+
181
+ ## Contributing
182
+
183
+ Bug reports and pull requests are welcome on GitHub at https://github.com/skryukov/inertia_rails-contrib.
184
+
185
+ ## License
186
+
187
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,16 @@
1
+ require "rails/generators/rails/controller/controller_generator"
2
+ require "inertia_rails_contrib/generators_helper"
3
+
4
+ module Inertia
5
+ module Generators
6
+ class ControllerGenerator < Rails::Generators::ControllerGenerator
7
+ include InertiaRailsContrib::GeneratorsHelper
8
+
9
+ source_root File.expand_path("./templates", __dir__)
10
+
11
+ remove_hook_for :template_engine
12
+
13
+ hook_for :inertia_templates, required: true, default: InertiaRailsContrib::GeneratorsHelper.guess_inertia_template
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Controller < <%= parent_class_name.classify %>
3
+ <% actions.each do |action| -%>
4
+ def <%= action %>
5
+ render inertia: '<%= "#{inertia_base_path}/#{action.camelize}" %>'
6
+ end
7
+ <%= "\n" unless action == actions.last -%>
8
+ <% end -%>
9
+ end
10
+ <% end -%>
@@ -0,0 +1,151 @@
1
+ module Inertia
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("./templates", __dir__)
5
+
6
+ APPLICATION_LAYOUT = Rails.root.join("app/views/layouts/application.html.erb")
7
+
8
+ FRAMEWORKS = {
9
+ "react" => {
10
+ packages: %w[@inertiajs/react react react-dom],
11
+ dev_packages: %w[@vitejs/plugin-react],
12
+ vite_plugin_import: "import react from '@vitejs/plugin-react'",
13
+ vite_plugin_call: "react()",
14
+ copy_files: {
15
+ "InertiaExample.jsx" => "app/frontend/pages/InertiaExample.jsx",
16
+ "InertiaExample.module.css" => "app/frontend/pages/InertiaExample.module.css",
17
+ "../assets/react.svg" => "app/frontend/assets/react.svg",
18
+ "../assets/inertia.svg" => "app/frontend/assets/inertia.svg",
19
+ "../assets/vite_ruby.svg" => "app/frontend/assets/vite_ruby.svg"
20
+ }
21
+ },
22
+ "vue" => {
23
+ packages: %w[@inertiajs/vue3 vue],
24
+ dev_packages: %w[@vitejs/plugin-vue],
25
+ vite_plugin_import: "import vue from '@vitejs/plugin-vue'",
26
+ vite_plugin_call: "vue()",
27
+ copy_files: {
28
+ "InertiaExample.vue" => "app/frontend/pages/InertiaExample.vue",
29
+ "../assets/vue.svg" => "app/frontend/assets/vue.svg",
30
+ "../assets/inertia.svg" => "app/frontend/assets/inertia.svg",
31
+ "../assets/vite_ruby.svg" => "app/frontend/assets/vite_ruby.svg"
32
+ }
33
+ },
34
+ "svelte" => {
35
+ packages: %w[@inertiajs/svelte svelte @sveltejs/vite-plugin-svelte],
36
+ dev_packages: %w[@vitejs/plugin-vue],
37
+ vite_plugin_import: "import { svelte } from '@sveltejs/vite-plugin-svelte'",
38
+ vite_plugin_call: "svelte()",
39
+ copy_files: {
40
+ "svelte.config.js" => "svelte.config.js",
41
+ "InertiaExample.svelte" => "app/frontend/pages/InertiaExample.svelte",
42
+ "../assets/svelte.svg" => "app/frontend/assets/svelte.svg",
43
+ "../assets/inertia.svg" => "app/frontend/assets/inertia.svg",
44
+ "../assets/vite_ruby.svg" => "app/frontend/assets/vite_ruby.svg"
45
+ }
46
+ }
47
+ }
48
+
49
+ def install
50
+ say "Installing Inertia's Rails adapter"
51
+
52
+ if package_manager.nil?
53
+ say "Could not find a package.json file to install Inertia to.", :red
54
+ exit!
55
+ end
56
+
57
+ unless ruby_vite?
58
+ say "Could not find a Vite configuration file `config/vite.json`. This generator only supports Ruby on Rails with Vite.", :red
59
+ exit!
60
+ end
61
+
62
+ install_inertia
63
+
64
+ say "Inertia's Rails adapter successfully installed", :green
65
+ end
66
+
67
+ private
68
+
69
+ def install_inertia
70
+ say "Adding Inertia's Rails adapter initializer"
71
+ template "initializer.rb", Rails.root.join("config/initializers/inertia_rails.rb").to_s
72
+
73
+ say "Installing Inertia npm packages"
74
+ add_packages(*FRAMEWORKS[framework][:packages])
75
+ add_packages("--save-dev", *FRAMEWORKS[framework][:dev_packages])
76
+
77
+ unless File.read(vite_config_path).include?(FRAMEWORKS[framework][:vite_plugin_import])
78
+ say "Adding Vite plugin for #{framework}"
79
+ insert_into_file vite_config_path, "\n #{FRAMEWORKS[framework][:vite_plugin_call]},", after: "plugins: ["
80
+ prepend_file vite_config_path, "#{FRAMEWORKS[framework][:vite_plugin_import]}\n"
81
+ end
82
+
83
+ unless Rails.root.join("package.json").read.include?('"type": "module"')
84
+ say 'Add "type": "module", to the package.json file'
85
+ gsub_file Rails.root.join("package.json").to_s, /\A\s*\{/, "{\n \"type\": \"module\","
86
+ end
87
+
88
+ say "Copying inertia.js into Vite entrypoints", :blue
89
+ template "#{framework}/inertia.js", Rails.root.join("app/frontend/entrypoints/inertia.js").to_s
90
+
91
+ say "Adding inertia.js script tag to the application layout"
92
+ headers = <<-ERB
93
+ <%= vite_javascript_tag 'inertia' %>
94
+
95
+ <%= inertia_headers %>
96
+ ERB
97
+ insert_into_file APPLICATION_LAYOUT.to_s, headers, after: "<%= vite_client_tag %>\n"
98
+
99
+ if framework == "react" && !APPLICATION_LAYOUT.read.include?("vite_react_refresh_tag")
100
+ say "Adding Vite React Refresh tag to the application layout"
101
+ insert_into_file APPLICATION_LAYOUT.to_s, "<%= vite_react_refresh_tag %>\n ", before: "<%= vite_client_tag %>"
102
+ end
103
+
104
+ say "Copying example Inertia controller"
105
+ template "controller.rb", Rails.root.join("app/controllers/inertia_example_controller.rb").to_s
106
+
107
+ say "Adding a route for the example Inertia controller"
108
+ route "get 'inertia-example', to: 'inertia_example#index'"
109
+
110
+ say "Copying framework related files"
111
+ FRAMEWORKS[framework][:copy_files].each do |source, destination|
112
+ template "#{framework}/#{source}", Rails.root.join(destination).to_s
113
+ end
114
+ end
115
+
116
+ def ruby_vite?
117
+ Rails.root.join("config/vite.json").exist? && vite_config_path
118
+ end
119
+
120
+ def package_manager
121
+ return @package_manager if defined?(@package_manager)
122
+
123
+ @package_manager = detect_package_manager
124
+ end
125
+
126
+ def add_packages(*packages)
127
+ run "#{package_manager} add #{packages.join(" ")}"
128
+ end
129
+
130
+ def detect_package_manager
131
+ return nil unless Rails.root.join("package.json").exist?
132
+
133
+ if Rails.root.join("package-lock.json").exist?
134
+ "npm"
135
+ elsif Rails.root.join("bun.config.js").exist?
136
+ "bun"
137
+ else
138
+ "yarn"
139
+ end
140
+ end
141
+
142
+ def vite_config_path
143
+ @vite_config_path ||= Dir.glob(Rails.root.join("vite.config.{ts,js,mjs,cjs}")).first
144
+ end
145
+
146
+ def framework
147
+ @framework ||= ask("What framework do you want to use with Turbo Mount?", limited_to: FRAMEWORKS.keys, default: "react")
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1 @@
1
+ <svg width="100%" height="100%" viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg"><linearGradient id="a" x1="0" y1="200" x2="400" y2="200" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#9653ea"/><stop offset="1" stop-color="#6e74ef"/></linearGradient><path fill="url(#a)" fill-rule="evenodd" d="M400 200C400 89.543 310.457 0 200 0S0 89.543 0 200s89.543 200 200 200 200-89.543 200-200Z"/><path fill="#fff" d="M137.331 117.6H52.4l82.069 82.069L52.4 281.737h84.931L219.4 199.67Z"/><path fill="#fff" d="M265.231 117.6H180.3l82.069 82.069-82.069 82.068h84.931L347.3 199.67Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg viewBox="-10.5 -9.45 21 18.9" fill="none" xmlns="http://www.w3.org/2000/svg" class="uwu-hidden mt-4 mb-3 text-brand dark:text-brand-dark w-24 lg:w-28 self-center text-sm me-0 flex origin-center transition-all ease-in-out"><circle r="2" fill="#58C4DC"/><g stroke="#58C4DC"><ellipse rx="10" ry="4.5"/><ellipse rx="10" ry="4.5" transform="rotate(60)"/><ellipse rx="10" ry="4.5" transform="rotate(120)"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="iconify iconify--logos" width="26.6" height="32" viewBox="0 0 256 308"><path fill="#FF3E00" d="M239.682 40.707C211.113-.182 154.69-12.301 113.895 13.69L42.247 59.356a82.198 82.198 0 0 0-37.135 55.056 86.566 86.566 0 0 0 8.536 55.576 82.425 82.425 0 0 0-12.296 30.719 87.596 87.596 0 0 0 14.964 66.244c28.574 40.893 84.997 53.007 125.787 27.016l71.648-45.664a82.182 82.182 0 0 0 37.135-55.057 86.601 86.601 0 0 0-8.53-55.577 82.409 82.409 0 0 0 12.29-30.718 87.573 87.573 0 0 0-14.963-66.244"/><path fill="#FFF" d="M106.889 270.841c-23.102 6.007-47.497-3.036-61.103-22.648a52.685 52.685 0 0 1-9.003-39.85 49.978 49.978 0 0 1 1.713-6.693l1.35-4.115 3.671 2.697a92.447 92.447 0 0 0 28.036 14.007l2.663.808-.245 2.659a16.067 16.067 0 0 0 2.89 10.656 17.143 17.143 0 0 0 18.397 6.828 15.786 15.786 0 0 0 4.403-1.935l71.67-45.672a14.922 14.922 0 0 0 6.734-9.977 15.923 15.923 0 0 0-2.713-12.011 17.156 17.156 0 0 0-18.404-6.832 15.78 15.78 0 0 0-4.396 1.933l-27.35 17.434a52.298 52.298 0 0 1-14.553 6.391c-23.101 6.007-47.497-3.036-61.101-22.649a52.681 52.681 0 0 1-9.004-39.849 49.428 49.428 0 0 1 22.34-33.114l71.664-45.677a52.218 52.218 0 0 1 14.563-6.398c23.101-6.007 47.497 3.036 61.101 22.648a52.685 52.685 0 0 1 9.004 39.85 50.559 50.559 0 0 1-1.713 6.692l-1.35 4.116-3.67-2.693a92.373 92.373 0 0 0-28.037-14.013l-2.664-.809.246-2.658a16.099 16.099 0 0 0-2.89-10.656 17.143 17.143 0 0 0-18.398-6.828 15.786 15.786 0 0 0-4.402 1.935l-71.67 45.674a14.898 14.898 0 0 0-6.73 9.975 15.9 15.9 0 0 0 2.709 12.012 17.156 17.156 0 0 0 18.404 6.832 15.841 15.841 0 0 0 4.402-1.935l27.345-17.427a52.147 52.147 0 0 1 14.552-6.397c23.101-6.006 47.497 3.037 61.102 22.65a52.681 52.681 0 0 1 9.003 39.848 49.453 49.453 0 0 1-22.34 33.12l-71.664 45.673a52.218 52.218 0 0 1-14.563 6.398"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 366 304" fill="none"><path d="M91.95 46.973a5.5 5.5 0 0 0-.401.722l-59.724 69.638a5.5 5.5 0 0 0 .003 7.165l147 171.086a5.502 5.502 0 0 0 8.344 0l147-171.084a5.5 5.5 0 0 0 .003-7.165l-59.723-69.637a5.5 5.5 0 0 0-4.996-3.198H96.543a5.5 5.5 0 0 0-4.592 2.473z" fill="url(#a)" stroke="url(#b)" stroke-width="11" stroke-linecap="round" stroke-linejoin="round"/><path d="m265.857 19.004-116.154 5.598a4.346 4.346 0 0 0-3.643 3.885v109.121c-.267 2.885 2.326 5.217 5.182 4.659l20.815-4.659c3.114-.608 5.819 2.194 5.082 5.268l-8.01 45.423c-.767 3.199 2.18 6.052 5.371 5.201l17.232-3.395c3.195-.852 6.144 2.01 5.369 5.211l-18.069 74.653c-1.13 4.67 5.068 7.44 7.82 3.495l1.838-2.635L291.703 81.887c1.725-3.163-.947-6.923-4.518-6.357l-34.224 5.417c-3.217.508-5.839-2.544-4.834-5.627l22.576-50.691c1.006-3.088-1.626-6.144-4.846-5.625z" fill="url(#c)"/><defs><linearGradient id="a" x1="28.5" y1="34" x2="246.355" y2="194.428" gradientUnits="userSpaceOnUse"><stop stop-color="#FF006B"/><stop offset=".364" stop-color="#C00"/><stop offset="1" stop-color="#980D03"/></linearGradient><linearGradient id="b" x1="28.5" y1="34" x2="246.355" y2="194.428" gradientUnits="userSpaceOnUse"><stop stop-color="#FF006B"/><stop offset=".364" stop-color="#C00"/><stop offset="1" stop-color="#980D03"/></linearGradient><linearGradient id="c" x1="183.666" y1="-5.499" x2="211.353" y2="242.278" gradientUnits="userSpaceOnUse"><stop stop-color="#FFDD35"/><stop offset=".083" stop-color="#FFD233"/><stop offset=".594" stop-color="#FFA800"/><stop offset=".839" stop-color="#F90"/></linearGradient></defs></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="iconify iconify--logos" width="37.07" height="36" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8 0 0h97.92L128 51.2 157.44 0h47.36Z"/><path fill="#41B883" d="m0 0 128 220.8L256 0h-51.2L128 132.48 50.56 0H0Z"/><path fill="#35495E" d="M50.56 0 128 133.12 204.8 0h-47.36L128 51.2 97.92 0H50.56Z"/></svg>
@@ -0,0 +1,7 @@
1
+ class InertiaExampleController < ApplicationController
2
+ def index
3
+ render inertia: "InertiaExample", props: {
4
+ name: params.fetch(:name, "World")
5
+ }
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ InertiaRails.configure do |config|
2
+ config.ssr_enabled = ViteRuby.config.ssr_build_enabled
3
+ config.version = ViteRuby.digest
4
+ end
@@ -0,0 +1,60 @@
1
+ import { Head } from '@inertiajs/react'
2
+ import { useState } from 'react'
3
+
4
+ import reactSvg from '/assets/react.svg'
5
+ import inertiaSvg from '/assets/inertia.svg'
6
+ import viteRubySvg from '/assets/vite_ruby.svg'
7
+
8
+ import cs from './InertiaExample.module.css'
9
+
10
+ export default function InertiaExample({ name }) {
11
+ const [count, setCount] = useState(0)
12
+
13
+ return (
14
+ <>
15
+ <Head title="Inertia + Vite Ruby + React Example" />
16
+
17
+ <div className={cs.root}>
18
+ <h1 className={cs.h1}>Hello {name}!</h1>
19
+
20
+ <div>
21
+ <a href="https://inertia-rails.netlify.app" target="_blank">
22
+ <img className={cs.logo} src={inertiaSvg} alt="Inertia logo" />
23
+ </a>
24
+ <a href="https://vite-ruby.netlify.app" target="_blank">
25
+ <img
26
+ className={`${cs.logo} ${cs.vite}`}
27
+ src={viteRubySvg}
28
+ alt="Vite Ruby logo"
29
+ />
30
+ </a>
31
+ <a href="https://react.dev" target="_blank">
32
+ <img
33
+ className={`${cs.logo} ${cs.react}`}
34
+ src={reactSvg}
35
+ alt="React logo"
36
+ />
37
+ </a>
38
+ </div>
39
+
40
+ <h2 className={cs.h2}>Inertia + Vite Ruby + React</h2>
41
+
42
+ <div className="card">
43
+ <button
44
+ className={cs.button}
45
+ onClick={() => setCount((count) => count + 1)}
46
+ >
47
+ count is {count}
48
+ </button>
49
+ <p>
50
+ Edit <code>app/frontend/pages/InertiaExample.jsx</code> and save to
51
+ test HMR
52
+ </p>
53
+ </div>
54
+ <p className={cs.readTheDocs}>
55
+ Click on the Inertia, Vite Ruby, and React logos to learn more
56
+ </p>
57
+ </div>
58
+ </>
59
+ )
60
+ }
@@ -0,0 +1,80 @@
1
+ .root {
2
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3
+ line-height: 1.5;
4
+ font-weight: 400;
5
+ color: #213547;
6
+ background-color: #ffffff;
7
+ max-width: 1280px;
8
+ margin: 0 auto;
9
+ padding: 2rem;
10
+ text-align: center;
11
+ }
12
+
13
+ .h1 {
14
+ font-size: 3.2em;
15
+ line-height: 1.1;
16
+ }
17
+
18
+ .h2 {
19
+ font-size: 2.6em;
20
+ line-height: 1.1;
21
+ }
22
+
23
+ .button {
24
+ border-radius: 8px;
25
+ border: 1px solid transparent;
26
+ padding: 0.6em 1.2em;
27
+ font-size: 1em;
28
+ font-weight: 500;
29
+ font-family: inherit;
30
+ background-color: #f9f9f9;
31
+ cursor: pointer;
32
+ transition: border-color 0.25s;
33
+ }
34
+ .button:hover {
35
+ border-color: #646cff;
36
+ }
37
+ .button:focus,
38
+ .button:focus-visible {
39
+ outline: 4px auto -webkit-focus-ring-color;
40
+ }
41
+
42
+ .logo {
43
+ display: inline-block;
44
+ height: 6em;
45
+ padding: 1.5em;
46
+ will-change: filter;
47
+ transition: filter 300ms;
48
+ }
49
+ .logo:hover {
50
+ filter: drop-shadow(0 0 2em #646cffaa);
51
+ }
52
+ .logo.vite:hover {
53
+ filter: drop-shadow(0 0 2em #e4023baa);
54
+ }
55
+ .logo.react:hover {
56
+ filter: drop-shadow(0 0 2em #61dafbaa);
57
+ }
58
+
59
+ @keyframes logo-spin {
60
+ from {
61
+ transform: rotate(0deg);
62
+ }
63
+ to {
64
+ transform: rotate(360deg);
65
+ }
66
+ }
67
+
68
+ @media (prefers-reduced-motion: no-preference) {
69
+ .logo.react {
70
+ animation: logo-spin infinite 20s linear;
71
+ }
72
+ }
73
+
74
+ .card {
75
+ padding: 2em;
76
+ }
77
+
78
+ .read-the-docs {
79
+ color: #888;
80
+ }
@@ -0,0 +1,34 @@
1
+ import { createInertiaApp } from '@inertiajs/react'
2
+ import { createElement } from 'react'
3
+ import { createRoot } from 'react-dom/client'
4
+
5
+ createInertiaApp({
6
+ // Set default page title
7
+ // see https://inertia-rails.netlify.app/guide/title-and-meta
8
+ //
9
+ // title: title => title ? `${title} - App` : 'App',
10
+
11
+ // Disable progress bar
12
+ //
13
+ // see https://inertia-rails.netlify.app/guide/progress-indicators
14
+ // progress: false,
15
+
16
+ resolve: (name) => {
17
+ const pages = import.meta.glob('../pages/**/*.jsx', { eager: true })
18
+ return pages[`../pages/${name}.jsx`]
19
+
20
+ // To use a default layout, import the Layout component
21
+ // and use the following lines.
22
+ // see https://inertia-rails.netlify.app/guide/pages#default-layouts
23
+ //
24
+ // const page = pages[`./pages/${name}.jsx`]
25
+ // page.default.layout ||= (page) => createElement(Layout, null, page)
26
+ // return page
27
+ },
28
+
29
+ setup({ el, App, props }) {
30
+ const root = createRoot(el)
31
+
32
+ root.render(createElement(App, props))
33
+ },
34
+ })