inertiax_rails 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/push.yml +33 -0
  3. data/.gitignore +22 -0
  4. data/.rspec +3 -0
  5. data/CHANGELOG.md +173 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +7 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +273 -0
  10. data/Rakefile +6 -0
  11. data/app/controllers/inertia_rails/static_controller.rb +7 -0
  12. data/app/views/inertia.html.erb +1 -0
  13. data/app/views/inertia_ssr.html.erb +1 -0
  14. data/bin/console +14 -0
  15. data/bin/setup +8 -0
  16. data/inertiax_rails.gemspec +37 -0
  17. data/lib/generators/inertia_rails/install/controller.rb +7 -0
  18. data/lib/generators/inertia_rails/install/react/InertiaExample.jsx +9 -0
  19. data/lib/generators/inertia_rails/install/react/inertia.jsx +17 -0
  20. data/lib/generators/inertia_rails/install/svelte/InertiaExample.svelte +11 -0
  21. data/lib/generators/inertia_rails/install/svelte/inertia.js +14 -0
  22. data/lib/generators/inertia_rails/install/vue/InertiaExample.vue +11 -0
  23. data/lib/generators/inertia_rails/install/vue/inertia.js +20 -0
  24. data/lib/generators/inertia_rails/install_generator.rb +84 -0
  25. data/lib/inertia_rails/controller.rb +110 -0
  26. data/lib/inertia_rails/engine.rb +16 -0
  27. data/lib/inertia_rails/inertia_rails.rb +52 -0
  28. data/lib/inertia_rails/lazy.rb +28 -0
  29. data/lib/inertia_rails/middleware.rb +97 -0
  30. data/lib/inertia_rails/renderer.rb +92 -0
  31. data/lib/inertia_rails/rspec.rb +125 -0
  32. data/lib/inertia_rails/version.rb +3 -0
  33. data/lib/inertia_rails.rb +24 -0
  34. data/lib/patches/better_errors.rb +17 -0
  35. data/lib/patches/debug_exceptions/patch-5-0.rb +23 -0
  36. data/lib/patches/debug_exceptions/patch-5-1.rb +26 -0
  37. data/lib/patches/debug_exceptions.rb +17 -0
  38. data/lib/patches/mapper.rb +8 -0
  39. data/lib/patches/request.rb +9 -0
  40. data/lib/tasks/inertia_rails.rake +16 -0
  41. metadata +203 -0
@@ -0,0 +1,125 @@
1
+ require "rspec/core"
2
+ require "rspec/matchers"
3
+
4
+ module InertiaRails
5
+ module RSpec
6
+ class InertiaRenderWrapper
7
+ attr_reader :view_data, :props, :component
8
+
9
+ def initialize
10
+ @view_data = nil
11
+ @props = nil
12
+ @component = nil
13
+ end
14
+
15
+ def call(params)
16
+ set_values(params)
17
+ @render_method&.call(params)
18
+ end
19
+
20
+ def wrap_render(render_method)
21
+ @render_method = render_method
22
+ self
23
+ end
24
+
25
+ protected
26
+
27
+ def set_values(params)
28
+ @view_data = params[:locals].except(:page)
29
+ @props = params[:locals][:page][:props]
30
+ @component = params[:locals][:page][:component]
31
+ end
32
+ end
33
+
34
+ module Helpers
35
+ def inertia
36
+ raise 'Inertia test helpers aren\'t set up! Make sure you add inertia: true to describe blocks using inertia tests.' unless inertia_tests_setup?
37
+
38
+ if @_inertia_render_wrapper.nil? && !::RSpec.configuration.inertia[:skip_missing_renderer_warnings]
39
+ warn 'WARNING: the test never created an Inertia renderer. Maybe the code wasn\'t able to reach a `render inertia:` call? If this was intended, or you don\'t want to see this message, set ::RSpec.configuration.inertia[:skip_missing_renderer_warnings] = true'
40
+ end
41
+ @_inertia_render_wrapper
42
+ end
43
+
44
+ def expect_inertia
45
+ expect(inertia)
46
+ end
47
+
48
+ def inertia_wrap_render(render)
49
+ @_inertia_render_wrapper = InertiaRenderWrapper.new.wrap_render(render)
50
+ end
51
+
52
+ protected
53
+
54
+ def inertia_tests_setup?
55
+ ::RSpec.current_example.metadata.fetch(:inertia, false)
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ RSpec.configure do |config|
62
+ config.include ::InertiaRails::RSpec::Helpers
63
+ config.add_setting :inertia, default: {
64
+ skip_missing_renderer_warnings: false
65
+ }
66
+
67
+ config.before(:each, inertia: true) do
68
+ new_renderer = InertiaRails::Renderer.method(:new)
69
+ allow(InertiaRails::Renderer).to receive(:new) do |component, controller, request, response, render, named_args|
70
+ new_renderer.call(component, controller, request, response, inertia_wrap_render(render), **named_args)
71
+ end
72
+ end
73
+ end
74
+
75
+ RSpec::Matchers.define :have_exact_props do |expected_props|
76
+ match do |inertia|
77
+ # Computed props have symbolized keys.
78
+ expect(inertia.props).to eq expected_props.deep_symbolize_keys
79
+ end
80
+
81
+ failure_message do |inertia|
82
+ "expected inertia props to receive #{expected_props}, instead received #{inertia.props || 'nothing'}"
83
+ end
84
+ end
85
+
86
+ RSpec::Matchers.define :include_props do |expected_props|
87
+ match do |inertia|
88
+ # Computed props have symbolized keys.
89
+ expect(inertia.props).to include expected_props.deep_symbolize_keys
90
+ end
91
+
92
+ failure_message do |inertia|
93
+ "expected inertia props to include #{expected_props}, instead received #{inertia.props || 'nothing'}"
94
+ end
95
+ end
96
+
97
+ RSpec::Matchers.define :render_component do |expected_component|
98
+ match do |inertia|
99
+ expect(inertia.component).to eq expected_component
100
+ end
101
+
102
+ failure_message do |inertia|
103
+ "expected rendered inertia component to be #{expected_component}, instead received #{inertia.component || 'nothing'}"
104
+ end
105
+ end
106
+
107
+ RSpec::Matchers.define :have_exact_view_data do |expected_view_data|
108
+ match do |inertia|
109
+ expect(inertia.view_data).to eq expected_view_data
110
+ end
111
+
112
+ failure_message do |inertia|
113
+ "expected inertia view data to receive #{expected_view_data}, instead received #{inertia.view_data || 'nothing'}"
114
+ end
115
+ end
116
+
117
+ RSpec::Matchers.define :include_view_data do |expected_view_data|
118
+ match do |inertia|
119
+ expect(inertia.view_data).to include expected_view_data
120
+ end
121
+
122
+ failure_message do |inertia|
123
+ "expected inertia view data to include #{expected_view_data}, instead received #{inertia.view_data || 'nothing'}"
124
+ end
125
+ end
@@ -0,0 +1,3 @@
1
+ module InertiaRails
2
+ VERSION = "2.0.0"
3
+ end
@@ -0,0 +1,24 @@
1
+ require 'inertia_rails/renderer'
2
+ require 'inertia_rails/engine'
3
+
4
+ require 'patches/debug_exceptions'
5
+ require 'patches/better_errors'
6
+ require 'patches/request'
7
+ require 'patches/mapper'
8
+
9
+ ActionController::Renderers.add :inertia do |component, options|
10
+ InertiaRails::Renderer.new(
11
+ component,
12
+ self,
13
+ request,
14
+ response,
15
+ method(:render),
16
+ props: options[:props],
17
+ view_data: options[:view_data],
18
+ deep_merge: options[:deep_merge],
19
+ ).render
20
+ end
21
+
22
+ module InertiaRails
23
+ class Error < StandardError; end
24
+ end
@@ -0,0 +1,17 @@
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
+ if defined?(BetterErrors)
8
+ BetterErrors::Middleware.class_eval do
9
+ prepend(InertiaBetterErrors = Module.new do
10
+ def text?(env)
11
+ return false if env["HTTP_X_INERTIA"]
12
+
13
+ super
14
+ end
15
+ end)
16
+ end
17
+ end
@@ -0,0 +1,23 @@
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
+ ActionDispatch::DebugExceptions.class_eval do
8
+ prepend(InertiaDebugExceptions = Module.new do
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
@@ -0,0 +1,26 @@
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
+ ActionDispatch::DebugExceptions.class_eval do
10
+ prepend(InertiaDebugExceptions = Module.new do
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
@@ -0,0 +1,17 @@
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
@@ -0,0 +1,8 @@
1
+ ActionDispatch::Routing::Mapper.class_eval do
2
+ def inertia(args, &block)
3
+ route = args.keys.first
4
+ component = args.values.first
5
+
6
+ get(route => 'inertia_rails/static#static', defaults: {component: component})
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ ActionDispatch::Request.class_eval do
2
+ def inertia?
3
+ key? 'HTTP_X_INERTIA'
4
+ end
5
+
6
+ def inertia_partial?
7
+ key? 'HTTP_X_INERTIA_PARTIAL_DATA'
8
+ end
9
+ end
@@ -0,0 +1,16 @@
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
metadata ADDED
@@ -0,0 +1,203 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inertiax_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Brian Knoles
8
+ - Brandon Shar
9
+ - Eugene Granovsky
10
+ - Stefan Buhrmester
11
+ autorequire:
12
+ bindir: exe
13
+ cert_chain: []
14
+ date: 2024-07-25 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: railties
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: '5'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '5'
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - "~>"
35
+ - !ruby/object:Gem::Version
36
+ version: '2.0'
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '2.0'
44
+ - !ruby/object:Gem::Dependency
45
+ name: rake
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - "~>"
49
+ - !ruby/object:Gem::Version
50
+ version: '13.0'
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '13.0'
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec-rails
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: '4.0'
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '4.0'
72
+ - !ruby/object:Gem::Dependency
73
+ name: rails-controller-testing
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ - !ruby/object:Gem::Dependency
87
+ name: sqlite3
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ type: :development
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ - !ruby/object:Gem::Dependency
101
+ name: responders
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ - !ruby/object:Gem::Dependency
115
+ name: debug
116
+ requirement: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ description:
129
+ email:
130
+ - brain@bellawatt.com
131
+ - brandon@bellawatt.com
132
+ - eugene@bellawatt.com
133
+ - stefan@buhrmi.de
134
+ executables: []
135
+ extensions: []
136
+ extra_rdoc_files: []
137
+ files:
138
+ - ".github/workflows/push.yml"
139
+ - ".gitignore"
140
+ - ".rspec"
141
+ - CHANGELOG.md
142
+ - CODE_OF_CONDUCT.md
143
+ - Gemfile
144
+ - LICENSE.txt
145
+ - README.md
146
+ - Rakefile
147
+ - app/controllers/inertia_rails/static_controller.rb
148
+ - app/views/inertia.html.erb
149
+ - app/views/inertia_ssr.html.erb
150
+ - bin/console
151
+ - bin/setup
152
+ - inertiax_rails.gemspec
153
+ - lib/generators/inertia_rails/install/controller.rb
154
+ - lib/generators/inertia_rails/install/react/InertiaExample.jsx
155
+ - lib/generators/inertia_rails/install/react/inertia.jsx
156
+ - lib/generators/inertia_rails/install/svelte/InertiaExample.svelte
157
+ - lib/generators/inertia_rails/install/svelte/inertia.js
158
+ - lib/generators/inertia_rails/install/vue/InertiaExample.vue
159
+ - lib/generators/inertia_rails/install/vue/inertia.js
160
+ - lib/generators/inertia_rails/install_generator.rb
161
+ - lib/inertia_rails.rb
162
+ - lib/inertia_rails/controller.rb
163
+ - lib/inertia_rails/engine.rb
164
+ - lib/inertia_rails/inertia_rails.rb
165
+ - lib/inertia_rails/lazy.rb
166
+ - lib/inertia_rails/middleware.rb
167
+ - lib/inertia_rails/renderer.rb
168
+ - lib/inertia_rails/rspec.rb
169
+ - lib/inertia_rails/version.rb
170
+ - lib/patches/better_errors.rb
171
+ - lib/patches/debug_exceptions.rb
172
+ - lib/patches/debug_exceptions/patch-5-0.rb
173
+ - lib/patches/debug_exceptions/patch-5-1.rb
174
+ - lib/patches/mapper.rb
175
+ - lib/patches/request.rb
176
+ - lib/tasks/inertia_rails.rake
177
+ homepage: https://github.com/buhrmi/inertia-rails
178
+ licenses:
179
+ - MIT
180
+ metadata:
181
+ homepage_uri: https://github.com/buhrmi/inertia-rails
182
+ source_code_uri: https://github.com/buhrmi/inertia-rails
183
+ changelog_uri: https://github.com/buhrmi/inertia-rails/blob/master/CHANGELOG.md
184
+ post_install_message:
185
+ rdoc_options: []
186
+ require_paths:
187
+ - lib
188
+ required_ruby_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ required_rubygems_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ requirements: []
199
+ rubygems_version: 3.5.11
200
+ signing_key:
201
+ specification_version: 4
202
+ summary: Inertia adapter for Rails
203
+ test_files: []