inertia_rails 3.11.0 → 3.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/app/controllers/inertia_rails/static_controller.rb +2 -0
- data/lib/generators/inertia/install/install_generator.rb +8 -3
- data/lib/inertia_rails/action_filter.rb +2 -1
- data/lib/inertia_rails/controller.rb +20 -15
- data/lib/inertia_rails/defer_prop.rb +5 -16
- data/lib/inertia_rails/engine.rb +6 -4
- data/lib/inertia_rails/helper.rb +26 -22
- data/lib/inertia_rails/inertia_rails.rb +8 -2
- data/lib/inertia_rails/lazy_prop.rb +1 -1
- data/lib/inertia_rails/merge_prop.rb +3 -12
- data/lib/inertia_rails/prop_mergeable.rb +83 -0
- data/lib/inertia_rails/renderer.rb +122 -59
- data/lib/inertia_rails/rspec.rb +28 -19
- data/lib/inertia_rails/scroll_metadata.rb +97 -0
- data/lib/inertia_rails/scroll_prop.rb +35 -0
- data/lib/inertia_rails/version.rb +3 -1
- data/lib/patches/better_errors.rb +4 -4
- data/lib/patches/debug_exceptions.rb +27 -10
- data/lib/patches/mapper.rb +6 -1
- data/lib/patches/request.rb +2 -0
- data/lib/tasks/inertia_rails.rake +7 -5
- metadata +5 -4
- data/lib/patches/debug_exceptions/patch-5-0.rb +0 -27
- data/lib/patches/debug_exceptions/patch-5-1.rb +0 -30
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a3bde9e557a4d5b76450d4f019ae8461b40a0eb2fda2984d8d5cb32fa58d769c
|
|
4
|
+
data.tar.gz: d662136e29e4f72957a6677a74b1c6c29086e8e32056023e5b51fb4b5e70b976
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 86753985c32f435b2967144c8b88e22984d1999fd0e528ac862d9b2dcc081545d52841d54b984d8184cb7774681576aa03ce244b09016a79b0110067b1d69d7e
|
|
7
|
+
data.tar.gz: 22197c8fc07a0f2d25402f04ab9988b3a572bd7c713ef8a391bf95bdb680bfac5a03c65c19796671d7172f921d1fdc900cc9f4f3d41420702e556a1a820a3942
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [3.12.1] - 2025-11-09
|
|
8
|
+
|
|
9
|
+
* Fix scroll props and deferred props for shared data (@bknoles)
|
|
10
|
+
* Deprecate the probably-no-actually-used-anywhere public readers on InertiaRails::Renderer (@bknoles)
|
|
11
|
+
|
|
12
|
+
## [3.12.0] - 2025-11-08
|
|
13
|
+
|
|
14
|
+
* Docs updates (@leenyburger, @skryukov, @bn-l)
|
|
15
|
+
* Reimplement devcontainers (@kieraneglin)
|
|
16
|
+
* Support for Inertia.js infinite scroll components (@skyrukov)
|
|
17
|
+
* New merge options (@skryukov)
|
|
18
|
+
|
|
7
19
|
## [3.11.0] - 2025-08-29
|
|
8
20
|
|
|
9
21
|
* Fix Svelte generator (@skryukov)
|
|
@@ -128,8 +128,12 @@ module Inertia
|
|
|
128
128
|
add_dependencies(*FRAMEWORKS[framework]['packages_ts'])
|
|
129
129
|
|
|
130
130
|
say 'Copying adding scripts to package.json'
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
if svelte?
|
|
132
|
+
run 'npm pkg set scripts.check="svelte-check --tsconfig ./tsconfig.json && tsc -p tsconfig.node.json"'
|
|
133
|
+
end
|
|
134
|
+
if framework == 'vue'
|
|
135
|
+
run 'npm pkg set scripts.check="vue-tsc -p tsconfig.app.json && tsc -p tsconfig.node.json"'
|
|
136
|
+
end
|
|
133
137
|
run 'npm pkg set scripts.check="tsc -p tsconfig.app.json && tsc -p tsconfig.node.json"' if framework == 'react'
|
|
134
138
|
end
|
|
135
139
|
|
|
@@ -262,8 +266,9 @@ module Inertia
|
|
|
262
266
|
end
|
|
263
267
|
|
|
264
268
|
def inertia_resolved_version
|
|
269
|
+
package = "@inertiajs/core@#{options[:inertia_version]}"
|
|
265
270
|
@inertia_resolved_version ||= Gem::Version.new(
|
|
266
|
-
`npm show
|
|
271
|
+
`npm show #{package} version --json | tail -n2 | head -n1 | tr -d '", '`.strip
|
|
267
272
|
)
|
|
268
273
|
end
|
|
269
274
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
#
|
|
3
4
|
# Based on AbstractController::Callbacks::ActionFilter
|
|
4
5
|
# https://github.com/rails/rails/blob/v7.2.0/actionpack/lib/abstract_controller/callbacks.rb#L39
|
|
@@ -6,7 +7,7 @@ module InertiaRails
|
|
|
6
7
|
class ActionFilter
|
|
7
8
|
def initialize(conditional_key, actions)
|
|
8
9
|
@conditional_key = conditional_key
|
|
9
|
-
@actions = Array(actions).
|
|
10
|
+
@actions = Array(actions).to_set(&:to_s)
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def match?(controller)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'inertia_rails'
|
|
4
|
+
require_relative 'helper'
|
|
5
|
+
require_relative 'action_filter'
|
|
6
|
+
require_relative 'meta_tag_builder'
|
|
5
7
|
|
|
6
8
|
module InertiaRails
|
|
7
9
|
module Controller
|
|
@@ -21,8 +23,8 @@ module InertiaRails
|
|
|
21
23
|
return push_to_inertia_share(**(hash || props), &block) if options.empty?
|
|
22
24
|
|
|
23
25
|
push_to_inertia_share do
|
|
24
|
-
next
|
|
25
|
-
next
|
|
26
|
+
next if options[:if] && !options[:if].all? { |filter| instance_exec(&filter) }
|
|
27
|
+
next if options[:unless]&.any? { |filter| instance_exec(&filter) }
|
|
26
28
|
|
|
27
29
|
next hash unless block
|
|
28
30
|
|
|
@@ -81,7 +83,9 @@ module InertiaRails
|
|
|
81
83
|
return options if options.empty?
|
|
82
84
|
|
|
83
85
|
if props.except(:if, :unless, :only, :except).any?
|
|
84
|
-
raise ArgumentError,
|
|
86
|
+
raise ArgumentError,
|
|
87
|
+
'You must not mix shared data and [:if, :unless, :only, :except] options, ' \
|
|
88
|
+
'pass data as a hash or a block.'
|
|
85
89
|
end
|
|
86
90
|
|
|
87
91
|
transform_inertia_share_option(options, :only, :if)
|
|
@@ -110,7 +114,7 @@ module InertiaRails
|
|
|
110
114
|
when InertiaRails::ActionFilter
|
|
111
115
|
-> { filter.match?(self) }
|
|
112
116
|
else
|
|
113
|
-
raise ArgumentError,
|
|
117
|
+
raise ArgumentError, 'You must pass a symbol or a proc as a filter.'
|
|
114
118
|
end
|
|
115
119
|
end
|
|
116
120
|
end
|
|
@@ -136,6 +140,7 @@ module InertiaRails
|
|
|
136
140
|
|
|
137
141
|
def inertia_view_assigns
|
|
138
142
|
return {} unless @_inertia_instance_props
|
|
143
|
+
|
|
139
144
|
view_assigns.except(*@_inertia_skip_props)
|
|
140
145
|
end
|
|
141
146
|
|
|
@@ -152,22 +157,22 @@ module InertiaRails
|
|
|
152
157
|
else
|
|
153
158
|
if inertia_configuration.always_include_errors_hash.nil?
|
|
154
159
|
InertiaRails.deprecator.warn(
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
160
|
+
'To comply with the Inertia protocol, an empty errors hash `{errors: {}}` ' \
|
|
161
|
+
'will be included to all responses by default starting with InertiaRails 4.0. ' \
|
|
162
|
+
'To opt-in now, set `config.always_include_errors_hash = true`. ' \
|
|
163
|
+
'To disable this warning, set it to `false`.'
|
|
159
164
|
)
|
|
160
165
|
end
|
|
161
166
|
{}
|
|
162
167
|
end
|
|
163
168
|
|
|
164
|
-
self.class._inertia_shared_data.filter_map
|
|
169
|
+
self.class._inertia_shared_data.filter_map do |shared_data|
|
|
165
170
|
if shared_data.respond_to?(:call)
|
|
166
171
|
instance_exec(&shared_data)
|
|
167
172
|
else
|
|
168
173
|
shared_data
|
|
169
174
|
end
|
|
170
|
-
|
|
175
|
+
end.reduce(initial_data, &:merge)
|
|
171
176
|
end
|
|
172
177
|
|
|
173
178
|
def inertia_location(url)
|
|
@@ -183,7 +188,7 @@ module InertiaRails
|
|
|
183
188
|
session[:inertia_errors] = inertia_errors.to_hash
|
|
184
189
|
else
|
|
185
190
|
InertiaRails.deprecator.warn(
|
|
186
|
-
|
|
191
|
+
'Object passed to `inertia: { errors: ... }` must respond to `to_hash`. Pass a hash-like object instead.'
|
|
187
192
|
)
|
|
188
193
|
session[:inertia_errors] = inertia_errors
|
|
189
194
|
end
|
|
@@ -2,27 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
module InertiaRails
|
|
4
4
|
class DeferProp < IgnoreOnFirstLoadProp
|
|
5
|
-
|
|
5
|
+
prepend PropMergeable
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
DEFAULT_GROUP = 'default'
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
raise ArgumentError, 'Cannot set both `deep_merge` and `merge` to true' if deep_merge && merge
|
|
9
|
+
attr_reader :group
|
|
11
10
|
|
|
11
|
+
def initialize(**props, &block)
|
|
12
12
|
super(&block)
|
|
13
13
|
|
|
14
|
-
@group = group || DEFAULT_GROUP
|
|
15
|
-
@merge = merge || deep_merge
|
|
16
|
-
@deep_merge = deep_merge
|
|
17
|
-
@match_on = match_on.nil? ? nil : Array(match_on)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def merge?
|
|
21
|
-
@merge
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def deep_merge?
|
|
25
|
-
@deep_merge
|
|
14
|
+
@group = props[:group] || DEFAULT_GROUP
|
|
26
15
|
end
|
|
27
16
|
end
|
|
28
17
|
end
|
data/lib/inertia_rails/engine.rb
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'middleware'
|
|
4
|
+
require_relative 'controller'
|
|
3
5
|
|
|
4
6
|
module InertiaRails
|
|
5
7
|
class Engine < ::Rails::Engine
|
|
6
|
-
initializer
|
|
8
|
+
initializer 'inertia_rails.configure_rails_initialization' do |app|
|
|
7
9
|
app.middleware.use ::InertiaRails::Middleware
|
|
8
10
|
end
|
|
9
11
|
|
|
10
|
-
initializer
|
|
12
|
+
initializer 'inertia_rails.action_controller' do
|
|
11
13
|
ActiveSupport.on_load(:action_controller_base) do
|
|
12
14
|
include ::InertiaRails::Controller
|
|
13
15
|
end
|
data/lib/inertia_rails/helper.rb
CHANGED
|
@@ -1,32 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require_relative 'inertia_rails'
|
|
2
4
|
|
|
3
|
-
module InertiaRails
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
module InertiaRails
|
|
6
|
+
module Helper
|
|
7
|
+
def inertia_ssr_head
|
|
8
|
+
controller.instance_variable_get('@_inertia_ssr_head')
|
|
9
|
+
end
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
def inertia_headers
|
|
12
|
+
InertiaRails.deprecator.warn(
|
|
13
|
+
'`inertia_headers` is deprecated and will be removed in InertiaRails 4.0, use `inertia_ssr_head` instead.'
|
|
14
|
+
)
|
|
15
|
+
inertia_ssr_head
|
|
16
|
+
end
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
def inertia_rendering?
|
|
19
|
+
controller.instance_variable_get('@_inertia_rendering')
|
|
20
|
+
end
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
def inertia_page
|
|
23
|
+
controller.instance_variable_get('@_inertia_page')
|
|
24
|
+
end
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
def inertia_meta_tags
|
|
27
|
+
meta_tag_data = (inertia_page || {}).dig(:props, :_inertia_meta) || []
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
meta_tags = meta_tag_data.map do |inertia_meta_tag|
|
|
30
|
+
inertia_meta_tag.to_tag(tag)
|
|
31
|
+
end
|
|
29
32
|
|
|
30
|
-
|
|
33
|
+
safe_join(meta_tags, "\n")
|
|
34
|
+
end
|
|
31
35
|
end
|
|
32
36
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'inertia_rails/prop_mergeable'
|
|
3
4
|
require 'inertia_rails/base_prop'
|
|
4
5
|
require 'inertia_rails/ignore_on_first_load_prop'
|
|
5
6
|
require 'inertia_rails/always_prop'
|
|
@@ -7,6 +8,7 @@ require 'inertia_rails/lazy_prop'
|
|
|
7
8
|
require 'inertia_rails/optional_prop'
|
|
8
9
|
require 'inertia_rails/defer_prop'
|
|
9
10
|
require 'inertia_rails/merge_prop'
|
|
11
|
+
require 'inertia_rails/scroll_prop'
|
|
10
12
|
require 'inertia_rails/configuration'
|
|
11
13
|
require 'inertia_rails/meta_tag'
|
|
12
14
|
|
|
@@ -34,8 +36,8 @@ module InertiaRails
|
|
|
34
36
|
AlwaysProp.new(&block)
|
|
35
37
|
end
|
|
36
38
|
|
|
37
|
-
def merge(
|
|
38
|
-
MergeProp.new(
|
|
39
|
+
def merge(...)
|
|
40
|
+
MergeProp.new(...)
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
def deep_merge(match_on: nil, &block)
|
|
@@ -45,5 +47,9 @@ module InertiaRails
|
|
|
45
47
|
def defer(group: nil, merge: nil, deep_merge: nil, match_on: nil, &block)
|
|
46
48
|
DeferProp.new(group: group, merge: merge, deep_merge: deep_merge, match_on: match_on, &block)
|
|
47
49
|
end
|
|
50
|
+
|
|
51
|
+
def scroll(metadata = nil, **options, &block)
|
|
52
|
+
ScrollProp.new(metadata: metadata, **options, &block)
|
|
53
|
+
end
|
|
48
54
|
end
|
|
49
55
|
end
|
|
@@ -2,20 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
module InertiaRails
|
|
4
4
|
class MergeProp < BaseProp
|
|
5
|
-
|
|
5
|
+
prepend PropMergeable
|
|
6
6
|
|
|
7
|
-
def initialize(
|
|
7
|
+
def initialize(**_props, &block)
|
|
8
8
|
super(&block)
|
|
9
|
-
@
|
|
10
|
-
@match_on = match_on.nil? ? nil : Array(match_on)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def merge?
|
|
14
|
-
true
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def deep_merge?
|
|
18
|
-
@deep_merge
|
|
9
|
+
@merge = true
|
|
19
10
|
end
|
|
20
11
|
end
|
|
21
12
|
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module InertiaRails
|
|
4
|
+
module PropMergeable
|
|
5
|
+
attr_reader :match_on, :appends_at_paths, :prepends_at_paths
|
|
6
|
+
|
|
7
|
+
def initialize(**props, &block)
|
|
8
|
+
raise ArgumentError, 'Cannot set both `deep_merge` and `merge` to true' if props[:deep_merge] && props[:merge]
|
|
9
|
+
|
|
10
|
+
@deep_merge = props.fetch(:deep_merge, false)
|
|
11
|
+
@merge = props[:merge] || @deep_merge
|
|
12
|
+
@match_on = props[:match_on].nil? ? nil : Array(props[:match_on])
|
|
13
|
+
@appends_at_paths = []
|
|
14
|
+
@prepends_at_paths = []
|
|
15
|
+
@append = true
|
|
16
|
+
|
|
17
|
+
append(props[:append]) if props.key?(:append)
|
|
18
|
+
prepend(props[:prepend]) if props.key?(:prepend)
|
|
19
|
+
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def appends_at_root?
|
|
24
|
+
@append && merges_at_root?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def prepends_at_root?
|
|
28
|
+
!@append && merges_at_root?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def merges_at_root?
|
|
32
|
+
merge? && appends_at_paths.none? && prepends_at_paths.none?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def merge?
|
|
36
|
+
@merge
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def deep_merge?
|
|
40
|
+
@deep_merge
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def append(path, match_on: nil)
|
|
46
|
+
case path
|
|
47
|
+
when TrueClass, FalseClass
|
|
48
|
+
@append = path
|
|
49
|
+
when String
|
|
50
|
+
@appends_at_paths << path
|
|
51
|
+
when Array
|
|
52
|
+
@appends_at_paths += path
|
|
53
|
+
when Hash
|
|
54
|
+
@match_on ||= []
|
|
55
|
+
path.each do |key, value|
|
|
56
|
+
@appends_at_paths << key.to_s
|
|
57
|
+
@match_on << "#{key}.#{value}" if value
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
(@match_on ||= []) << "#{path}.#{match_on}" if match_on && path.is_a?(String)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def prepend(path, match_on: nil)
|
|
65
|
+
case path
|
|
66
|
+
when TrueClass, FalseClass
|
|
67
|
+
@append = !path
|
|
68
|
+
when String
|
|
69
|
+
@prepends_at_paths << path
|
|
70
|
+
when Array
|
|
71
|
+
@prepends_at_paths += path
|
|
72
|
+
when Hash
|
|
73
|
+
@match_on ||= []
|
|
74
|
+
path.each do |key, value|
|
|
75
|
+
@prepends_at_paths << key.to_s
|
|
76
|
+
@match_on << "#{key}.#{value}" if value
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
(@match_on ||= []) << "#{path}.#{match_on}" if match_on && path.is_a?(String)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -6,15 +6,15 @@ require_relative 'inertia_rails'
|
|
|
6
6
|
|
|
7
7
|
module InertiaRails
|
|
8
8
|
class Renderer
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
%i[component configuration controller props view_data encrypt_history
|
|
10
|
+
clear_history].each do |method_name|
|
|
11
|
+
define_method(method_name) do
|
|
12
|
+
InertiaRails.deprecator.warn(
|
|
13
|
+
"[DEPRECATION] Accessing `InertiaRails::Renderer##{method_name}` is deprecated and will be removed in v4.0"
|
|
14
|
+
)
|
|
15
|
+
instance_variable_get("@#{method_name}")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
18
|
|
|
19
19
|
def initialize(component, controller, request, response, render_method, **options)
|
|
20
20
|
if component.is_a?(Hash) && options.key?(:props)
|
|
@@ -24,15 +24,20 @@ module InertiaRails
|
|
|
24
24
|
|
|
25
25
|
@controller = controller
|
|
26
26
|
@configuration = controller.__send__(:inertia_configuration)
|
|
27
|
-
@component = resolve_component(component)
|
|
28
27
|
@request = request
|
|
29
28
|
@response = response
|
|
30
29
|
@render_method = render_method
|
|
31
|
-
@props = options.fetch(:props, component.is_a?(Hash) ? component : controller.__send__(:inertia_view_assigns))
|
|
32
30
|
@view_data = options.fetch(:view_data, {})
|
|
33
|
-
@
|
|
34
|
-
@encrypt_history = options.fetch(:encrypt_history, configuration.encrypt_history)
|
|
31
|
+
@encrypt_history = options.fetch(:encrypt_history, @configuration.encrypt_history)
|
|
35
32
|
@clear_history = options.fetch(:clear_history, controller.session[:inertia_clear_history] || false)
|
|
33
|
+
|
|
34
|
+
deep_merge = options.fetch(:deep_merge, @configuration.deep_merge_shared_data)
|
|
35
|
+
passed_props = options.fetch(:props,
|
|
36
|
+
component.is_a?(Hash) ? component : @controller.__send__(:inertia_view_assigns))
|
|
37
|
+
@props = merge_props(shared_data, passed_props, deep_merge)
|
|
38
|
+
|
|
39
|
+
@component = resolve_component(component)
|
|
40
|
+
|
|
36
41
|
@controller.instance_variable_set('@_inertia_rendering', true)
|
|
37
42
|
controller.inertia_meta.add(options[:meta]) if options[:meta]
|
|
38
43
|
end
|
|
@@ -48,32 +53,32 @@ module InertiaRails
|
|
|
48
53
|
@render_method.call json: page.to_json, status: @response.status, content_type: Mime[:json]
|
|
49
54
|
else
|
|
50
55
|
begin
|
|
51
|
-
return render_ssr if configuration.ssr_enabled
|
|
56
|
+
return render_ssr if @configuration.ssr_enabled
|
|
52
57
|
rescue StandardError
|
|
53
58
|
nil
|
|
54
59
|
end
|
|
55
|
-
controller.instance_variable_set('@_inertia_page', page)
|
|
56
|
-
@render_method.call template: 'inertia', layout: layout, locals: view_data.merge(page: page)
|
|
60
|
+
@controller.instance_variable_set('@_inertia_page', page)
|
|
61
|
+
@render_method.call template: 'inertia', layout: layout, locals: @view_data.merge(page: page)
|
|
57
62
|
end
|
|
58
63
|
end
|
|
59
64
|
|
|
60
65
|
private
|
|
61
66
|
|
|
62
67
|
def render_ssr
|
|
63
|
-
uri = URI("#{configuration.ssr_url}/render")
|
|
68
|
+
uri = URI("#{@configuration.ssr_url}/render")
|
|
64
69
|
res = JSON.parse(Net::HTTP.post(uri, page.to_json, 'Content-Type' => 'application/json').body)
|
|
65
70
|
|
|
66
|
-
controller.instance_variable_set('@_inertia_ssr_head', res['head'].join.html_safe)
|
|
67
|
-
@render_method.call html: res['body'].html_safe, layout: layout, locals: view_data.merge(page: page)
|
|
71
|
+
@controller.instance_variable_set('@_inertia_ssr_head', res['head'].join.html_safe)
|
|
72
|
+
@render_method.call html: res['body'].html_safe, layout: layout, locals: @view_data.merge(page: page)
|
|
68
73
|
end
|
|
69
74
|
|
|
70
75
|
def layout
|
|
71
|
-
layout = configuration.layout
|
|
76
|
+
layout = @configuration.layout
|
|
72
77
|
layout.nil? || layout
|
|
73
78
|
end
|
|
74
79
|
|
|
75
80
|
def shared_data
|
|
76
|
-
controller.__send__(:inertia_shared_data)
|
|
81
|
+
@controller.__send__(:inertia_shared_data)
|
|
77
82
|
end
|
|
78
83
|
|
|
79
84
|
# Cast props to symbol keyed hash before merging so that we have a consistent data structure and
|
|
@@ -81,8 +86,8 @@ module InertiaRails
|
|
|
81
86
|
#
|
|
82
87
|
# Functionally, this permits using either string or symbol keys in the controller. Since the results
|
|
83
88
|
# is cast to json, we should treat string/symbol keys as identical.
|
|
84
|
-
def merge_props(shared_props, props)
|
|
85
|
-
if
|
|
89
|
+
def merge_props(shared_props, props, deep_merge)
|
|
90
|
+
if deep_merge
|
|
86
91
|
shared_props.deep_symbolize_keys.deep_merge!(props.deep_symbolize_keys)
|
|
87
92
|
else
|
|
88
93
|
shared_props.symbolize_keys.merge(props.symbolize_keys)
|
|
@@ -91,47 +96,39 @@ module InertiaRails
|
|
|
91
96
|
|
|
92
97
|
def computed_props
|
|
93
98
|
# rubocop:disable Style/MultilineBlockChain
|
|
94
|
-
|
|
95
|
-
.
|
|
99
|
+
@props
|
|
100
|
+
.tap do |merged_props| # Always keep errors in the props
|
|
96
101
|
if merged_props.key?(:errors) && !merged_props[:errors].is_a?(BaseProp)
|
|
97
102
|
errors = merged_props[:errors]
|
|
98
103
|
merged_props[:errors] = InertiaRails.always { errors }
|
|
99
104
|
end
|
|
100
|
-
merged_props
|
|
101
105
|
end
|
|
102
106
|
.then { |props| deep_transform_props(props) } # Internal hydration/filtering
|
|
103
|
-
.then { |props| configuration.prop_transformer(props: props) } # Apply user-defined prop transformer
|
|
104
|
-
.tap
|
|
105
|
-
|
|
107
|
+
.then { |props| @configuration.prop_transformer(props: props) } # Apply user-defined prop transformer
|
|
108
|
+
.tap do |props| # Add meta tags last (never transformed)
|
|
109
|
+
props[:_inertia_meta] = meta_tags if meta_tags.present?
|
|
110
|
+
end
|
|
106
111
|
# rubocop:enable Style/MultilineBlockChain
|
|
107
112
|
end
|
|
108
113
|
|
|
109
114
|
def page
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
return @page if defined?(@page)
|
|
116
|
+
|
|
117
|
+
@page = {
|
|
118
|
+
component: @component,
|
|
112
119
|
props: computed_props,
|
|
113
120
|
url: @request.original_fullpath,
|
|
114
|
-
version: configuration.version,
|
|
115
|
-
encryptHistory: encrypt_history,
|
|
116
|
-
clearHistory: clear_history,
|
|
121
|
+
version: @configuration.version,
|
|
122
|
+
encryptHistory: @encrypt_history,
|
|
123
|
+
clearHistory: @clear_history,
|
|
117
124
|
}
|
|
118
125
|
|
|
119
126
|
deferred_props = deferred_props_keys
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
prop.deep_merge?
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
match_props_on = all_merge_props.filter_map do |key, prop|
|
|
127
|
-
prop.match_on.map { |ms| "#{key}.#{ms}" } if prop.match_on.present?
|
|
128
|
-
end.flatten
|
|
127
|
+
@page[:deferredProps] = deferred_props if deferred_props.present?
|
|
128
|
+
@page[:scrollProps] = scroll_props if scroll_props.present?
|
|
129
|
+
@page.merge!(resolve_merge_props)
|
|
129
130
|
|
|
130
|
-
|
|
131
|
-
default_page[:deepMergeProps] = deep_merge_props.map(&:first) if deep_merge_props.present?
|
|
132
|
-
default_page[:matchPropsOn] = match_props_on if match_props_on.present?
|
|
133
|
-
|
|
134
|
-
default_page
|
|
131
|
+
@page
|
|
135
132
|
end
|
|
136
133
|
|
|
137
134
|
def deep_transform_props(props, parent_path = [])
|
|
@@ -145,9 +142,9 @@ module InertiaRails
|
|
|
145
142
|
transformed_props[key] =
|
|
146
143
|
case prop
|
|
147
144
|
when BaseProp
|
|
148
|
-
prop.call(controller)
|
|
145
|
+
prop.call(@controller)
|
|
149
146
|
when Proc
|
|
150
|
-
controller.instance_exec(&prop)
|
|
147
|
+
@controller.instance_exec(&prop)
|
|
151
148
|
else
|
|
152
149
|
prop
|
|
153
150
|
end
|
|
@@ -163,10 +160,28 @@ module InertiaRails
|
|
|
163
160
|
end
|
|
164
161
|
end
|
|
165
162
|
|
|
166
|
-
def
|
|
167
|
-
|
|
163
|
+
def resolve_merge_props
|
|
164
|
+
deep_merge_props, merge_props = all_merge_props.partition do |_key, prop|
|
|
165
|
+
prop.deep_merge?
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
{
|
|
169
|
+
mergeProps: append_merge_props(merge_props),
|
|
170
|
+
prependProps: prepend_merge_props(merge_props),
|
|
171
|
+
deepMergeProps: deep_merge_props.map!(&:first),
|
|
172
|
+
matchPropsOn: resolve_match_on_props,
|
|
173
|
+
}.delete_if { |_, v| v.blank? }
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def resolve_match_on_props
|
|
177
|
+
all_merge_props.filter_map do |key, prop|
|
|
178
|
+
prop.match_on.map! { |ms| "#{key}.#{ms}" } if prop.match_on.present?
|
|
179
|
+
end.flatten
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def requested_merge_props
|
|
183
|
+
@requested_merge_props ||= @props.select do |key, prop|
|
|
168
184
|
next unless prop.try(:merge?)
|
|
169
|
-
next if reset_keys.include?(key)
|
|
170
185
|
next if rendering_partial_component? && (
|
|
171
186
|
(partial_keys.present? && partial_keys.exclude?(key.name)) ||
|
|
172
187
|
(partial_except_keys.present? && partial_except_keys.include?(key.name))
|
|
@@ -176,25 +191,73 @@ module InertiaRails
|
|
|
176
191
|
end
|
|
177
192
|
end
|
|
178
193
|
|
|
194
|
+
def append_merge_props(props)
|
|
195
|
+
return props if props.empty?
|
|
196
|
+
|
|
197
|
+
root_append_props, nested_append_props = props.partition { |_key, prop| prop.appends_at_root? }
|
|
198
|
+
|
|
199
|
+
result = Set.new(root_append_props.map!(&:first))
|
|
200
|
+
|
|
201
|
+
nested_append_props.each do |key, prop|
|
|
202
|
+
prop.appends_at_paths.each do |path|
|
|
203
|
+
result.add("#{key}.#{path}")
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
result.to_a
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def prepend_merge_props(props)
|
|
211
|
+
return props if props.empty?
|
|
212
|
+
|
|
213
|
+
root_prepend_props, nested_prepend_props = props.partition { |_key, prop| prop.prepends_at_root? }
|
|
214
|
+
|
|
215
|
+
result = Set.new(root_prepend_props.map!(&:first))
|
|
216
|
+
|
|
217
|
+
nested_prepend_props.each do |key, prop|
|
|
218
|
+
prop.prepends_at_paths.each do |path|
|
|
219
|
+
result.add("#{key}.#{path}")
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
result.to_a
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def scroll_props
|
|
227
|
+
return @scroll_props if defined?(@scroll_props)
|
|
228
|
+
|
|
229
|
+
@scroll_props = {}
|
|
230
|
+
requested_merge_props.each do |key, prop|
|
|
231
|
+
next unless prop.is_a?(ScrollProp)
|
|
232
|
+
|
|
233
|
+
@scroll_props[key] = prop.metadata.merge!(reset: reset_keys.include?(key))
|
|
234
|
+
end
|
|
235
|
+
@scroll_props
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def all_merge_props
|
|
239
|
+
@all_merge_props ||= requested_merge_props.reject { |key,| reset_keys.include?(key) }
|
|
240
|
+
end
|
|
241
|
+
|
|
179
242
|
def partial_keys
|
|
180
|
-
@partial_keys ||= (@request.headers['X-Inertia-Partial-Data'] || '').split(',').
|
|
243
|
+
@partial_keys ||= (@request.headers['X-Inertia-Partial-Data'] || '').split(',').compact_blank!
|
|
181
244
|
end
|
|
182
245
|
|
|
183
246
|
def reset_keys
|
|
184
|
-
(@request.headers['X-Inertia-Reset'] || '').split(',').
|
|
247
|
+
@reset_keys ||= (@request.headers['X-Inertia-Reset'] || '').split(',').compact_blank!.map!(&:to_sym)
|
|
185
248
|
end
|
|
186
249
|
|
|
187
250
|
def partial_except_keys
|
|
188
|
-
(@request.headers['X-Inertia-Partial-Except'] || '').split(',').
|
|
251
|
+
@partial_except_keys ||= (@request.headers['X-Inertia-Partial-Except'] || '').split(',').compact_blank!
|
|
189
252
|
end
|
|
190
253
|
|
|
191
254
|
def rendering_partial_component?
|
|
192
|
-
@request.headers['X-Inertia-Partial-Component'] == component
|
|
255
|
+
@request.headers['X-Inertia-Partial-Component'] == @component
|
|
193
256
|
end
|
|
194
257
|
|
|
195
258
|
def resolve_component(component)
|
|
196
259
|
if component == true || component.is_a?(Hash)
|
|
197
|
-
configuration.component_path_resolver(path: controller.controller_path, action: controller.action_name)
|
|
260
|
+
@configuration.component_path_resolver(path: @controller.controller_path, action: @controller.action_name)
|
|
198
261
|
else
|
|
199
262
|
component
|
|
200
263
|
end
|
|
@@ -230,7 +293,7 @@ module InertiaRails
|
|
|
230
293
|
end
|
|
231
294
|
|
|
232
295
|
def meta_tags
|
|
233
|
-
controller.inertia_meta.meta_tags
|
|
296
|
+
@controller.inertia_meta.meta_tags
|
|
234
297
|
end
|
|
235
298
|
end
|
|
236
299
|
end
|
data/lib/inertia_rails/rspec.rb
CHANGED
|
@@ -1,30 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rspec/core'
|
|
4
|
+
require 'rspec/matchers'
|
|
3
5
|
|
|
4
6
|
module InertiaRails
|
|
5
7
|
module RSpec
|
|
6
8
|
class InertiaRenderWrapper
|
|
7
9
|
attr_reader :view_data, :props, :component
|
|
8
|
-
|
|
10
|
+
|
|
9
11
|
def initialize
|
|
10
12
|
@view_data = nil
|
|
11
13
|
@props = nil
|
|
12
14
|
@component = nil
|
|
13
15
|
end
|
|
14
|
-
|
|
16
|
+
|
|
15
17
|
def call(params)
|
|
16
|
-
|
|
18
|
+
assign_locals(params)
|
|
17
19
|
@render_method&.call(params)
|
|
18
20
|
end
|
|
19
|
-
|
|
21
|
+
|
|
20
22
|
def wrap_render(render_method)
|
|
21
23
|
@render_method = render_method
|
|
22
24
|
self
|
|
23
25
|
end
|
|
24
|
-
|
|
26
|
+
|
|
25
27
|
protected
|
|
26
|
-
|
|
27
|
-
def
|
|
28
|
+
|
|
29
|
+
def assign_locals(params)
|
|
28
30
|
if params[:locals].present?
|
|
29
31
|
@view_data = params[:locals].except(:page)
|
|
30
32
|
@props = params[:locals][:page][:props]
|
|
@@ -33,18 +35,24 @@ module InertiaRails
|
|
|
33
35
|
# Sequential Inertia request
|
|
34
36
|
@view_data = {}
|
|
35
37
|
json = JSON.parse(params[:json])
|
|
36
|
-
@props = json[
|
|
37
|
-
@component = json[
|
|
38
|
+
@props = json['props']
|
|
39
|
+
@component = json['component']
|
|
38
40
|
end
|
|
39
41
|
end
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
module Helpers
|
|
43
45
|
def inertia
|
|
44
|
-
|
|
46
|
+
unless inertia_tests_setup?
|
|
47
|
+
raise "Inertia test helpers aren't set up! " \
|
|
48
|
+
'Make sure you add `inertia: true` to describe blocks using inertia tests.'
|
|
49
|
+
end
|
|
45
50
|
|
|
46
51
|
if @_inertia_render_wrapper.nil? && !::RSpec.configuration.inertia[:skip_missing_renderer_warnings]
|
|
47
|
-
warn 'WARNING: the test never created an Inertia renderer.
|
|
52
|
+
warn 'WARNING: the test never created an Inertia renderer. ' \
|
|
53
|
+
"Maybe the code wasn't able to reach a `render inertia:` call? If this was intended, " \
|
|
54
|
+
"or you don't want to see this message, " \
|
|
55
|
+
'set ::RSpec.configuration.inertia[:skip_missing_renderer_warnings] = true'
|
|
48
56
|
end
|
|
49
57
|
@_inertia_render_wrapper
|
|
50
58
|
end
|
|
@@ -57,8 +65,8 @@ module InertiaRails
|
|
|
57
65
|
@_inertia_render_wrapper = InertiaRenderWrapper.new.wrap_render(render)
|
|
58
66
|
end
|
|
59
67
|
|
|
60
|
-
protected
|
|
61
|
-
|
|
68
|
+
protected
|
|
69
|
+
|
|
62
70
|
def inertia_tests_setup?
|
|
63
71
|
::RSpec.current_example.metadata.fetch(:inertia, false)
|
|
64
72
|
end
|
|
@@ -67,9 +75,9 @@ module InertiaRails
|
|
|
67
75
|
end
|
|
68
76
|
|
|
69
77
|
RSpec.configure do |config|
|
|
70
|
-
config.include
|
|
78
|
+
config.include InertiaRails::RSpec::Helpers
|
|
71
79
|
config.add_setting :inertia, default: {
|
|
72
|
-
skip_missing_renderer_warnings: false
|
|
80
|
+
skip_missing_renderer_warnings: false,
|
|
73
81
|
}
|
|
74
82
|
|
|
75
83
|
config.before(:each, inertia: true) do
|
|
@@ -106,13 +114,14 @@ RSpec::Matchers.define :render_component do |expected_component|
|
|
|
106
114
|
end
|
|
107
115
|
|
|
108
116
|
failure_message do |inertia|
|
|
109
|
-
"expected rendered inertia component to be #{expected_component},
|
|
117
|
+
"expected rendered inertia component to be #{expected_component}, " \
|
|
118
|
+
"instead received #{inertia.component || 'nothing'}"
|
|
110
119
|
end
|
|
111
120
|
end
|
|
112
121
|
|
|
113
122
|
RSpec::Matchers.define :have_exact_view_data do |expected_view_data|
|
|
114
123
|
match do |inertia|
|
|
115
|
-
expect(inertia.view_data).to eq expected_view_data
|
|
124
|
+
expect(inertia.view_data).to eq expected_view_data
|
|
116
125
|
end
|
|
117
126
|
|
|
118
127
|
failure_message do |inertia|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module InertiaRails
|
|
4
|
+
module ScrollMetadata
|
|
5
|
+
class MissingMetadataAdapterError < StandardError; end
|
|
6
|
+
|
|
7
|
+
class Props
|
|
8
|
+
def initialize(page_name:, previous_page:, next_page:, current_page:)
|
|
9
|
+
@page_name = page_name
|
|
10
|
+
@previous_page = previous_page
|
|
11
|
+
@next_page = next_page
|
|
12
|
+
@current_page = current_page
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def as_json(_options = nil)
|
|
16
|
+
{
|
|
17
|
+
pageName: @page_name,
|
|
18
|
+
previousPage: @previous_page,
|
|
19
|
+
nextPage: @next_page,
|
|
20
|
+
currentPage: @current_page,
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class KaminariAdapter
|
|
26
|
+
def match?(metadata)
|
|
27
|
+
defined?(Kaminari) && metadata.is_a?(Kaminari::PageScopeMethods)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def call(metadata, **_options)
|
|
31
|
+
{
|
|
32
|
+
page_name: (Kaminari.config.param_name || 'page').to_s,
|
|
33
|
+
previous_page: metadata.prev_page,
|
|
34
|
+
next_page: metadata.next_page,
|
|
35
|
+
current_page: metadata.current_page,
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class PagyAdapter
|
|
41
|
+
def match?(metadata)
|
|
42
|
+
defined?(Pagy) && metadata.is_a?(Pagy)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def call(metadata, **_options)
|
|
46
|
+
page_name = metadata.respond_to?(:vars) ? metadata.vars.fetch(:page_param) : metadata.options[:page_key]
|
|
47
|
+
{
|
|
48
|
+
page_name: page_name.to_s,
|
|
49
|
+
previous_page: metadata.try(:prev) || metadata.try(:previous),
|
|
50
|
+
next_page: metadata.next,
|
|
51
|
+
current_page: metadata.page,
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class HashAdapter
|
|
57
|
+
def match?(metadata)
|
|
58
|
+
metadata.is_a?(Hash)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def call(metadata, **_options)
|
|
62
|
+
{
|
|
63
|
+
page_name: metadata.fetch(:page_name),
|
|
64
|
+
previous_page: metadata.fetch(:previous_page),
|
|
65
|
+
next_page: metadata.fetch(:next_page),
|
|
66
|
+
current_page: metadata.fetch(:current_page),
|
|
67
|
+
}
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class << self
|
|
72
|
+
attr_accessor :adapters
|
|
73
|
+
|
|
74
|
+
def extract(metadata, **options)
|
|
75
|
+
overrides = options.slice(:page_name, :previous_page, :next_page, :current_page)
|
|
76
|
+
|
|
77
|
+
adapters.each do |adapter|
|
|
78
|
+
next unless adapter.match?(metadata)
|
|
79
|
+
|
|
80
|
+
return Props.new(**adapter.call(metadata, **options).merge!(overrides)).as_json
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
begin
|
|
84
|
+
Props.new(**overrides).as_json
|
|
85
|
+
rescue ArgumentError
|
|
86
|
+
raise MissingMetadataAdapterError, "No ScrollMetadata adapter found for #{metadata}"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def register_adapter(adapter)
|
|
91
|
+
adapters.unshift(adapter.new)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
self.adapters = [KaminariAdapter, PagyAdapter, HashAdapter].map(&:new)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'scroll_metadata'
|
|
4
|
+
|
|
5
|
+
module InertiaRails
|
|
6
|
+
class ScrollProp < BaseProp
|
|
7
|
+
prepend PropMergeable
|
|
8
|
+
|
|
9
|
+
def initialize(**options, &block)
|
|
10
|
+
super(&block)
|
|
11
|
+
|
|
12
|
+
@merge = true
|
|
13
|
+
@metadata = options.delete(:metadata)
|
|
14
|
+
@wrapper = options.delete(:wrapper)
|
|
15
|
+
|
|
16
|
+
@options = options
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def call(controller)
|
|
20
|
+
@value = super
|
|
21
|
+
configure_merge_intent(controller.request.headers['X-Inertia-Infinite-Scroll-Merge-Intent'])
|
|
22
|
+
@value
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def metadata
|
|
26
|
+
ScrollMetadata.extract(@metadata, **@options)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def configure_merge_intent(scroll_intent)
|
|
32
|
+
scroll_intent == 'prepend' ? prepend(@wrapper || true) : append(@wrapper || true)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Patch BetterErrors::Middleware to render HTML for Inertia requests
|
|
2
4
|
#
|
|
3
5
|
# Original source:
|
|
@@ -7,13 +9,11 @@
|
|
|
7
9
|
module InertiaRails
|
|
8
10
|
module InertiaBetterErrors
|
|
9
11
|
def text?(env)
|
|
10
|
-
return false if env[
|
|
12
|
+
return false if env['HTTP_X_INERTIA']
|
|
11
13
|
|
|
12
14
|
super
|
|
13
15
|
end
|
|
14
16
|
end
|
|
15
17
|
end
|
|
16
18
|
|
|
17
|
-
if defined?(BetterErrors)
|
|
18
|
-
BetterErrors::Middleware.include InertiaRails::InertiaBetterErrors
|
|
19
|
-
end
|
|
19
|
+
BetterErrors::Middleware.include InertiaRails::InertiaBetterErrors if defined?(BetterErrors)
|
|
@@ -1,17 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Patch ActionDispatch::DebugExceptions to render HTML for Inertia requests
|
|
2
4
|
#
|
|
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
5
|
# The original source needs to be patched, so that Inertia requests are
|
|
7
6
|
# NOT responded with plain text, but with HTML.
|
|
7
|
+
#
|
|
8
|
+
# Original source (unchanged since Rails 5.1):
|
|
9
|
+
# https://github.com/rails/rails/blob/5-1-stable/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
|
|
10
|
+
# https://github.com/rails/rails/blob/8-0-stable/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
|
|
11
|
+
#
|
|
8
12
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
module InertiaRails
|
|
14
|
+
module InertiaDebugExceptions
|
|
15
|
+
def render_for_browser_request(request, wrapper)
|
|
16
|
+
template = create_template(request, wrapper)
|
|
17
|
+
file = "rescues/#{wrapper.rescue_template}"
|
|
18
|
+
|
|
19
|
+
if request.xhr? && !request.headers['X-Inertia'] # <<<< this line is changed only
|
|
20
|
+
body = template.render(template: file, layout: false, formats: [:text])
|
|
21
|
+
format = 'text/plain'
|
|
22
|
+
else
|
|
23
|
+
body = template.render(template: file, layout: 'rescues/layout')
|
|
24
|
+
format = 'text/html'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
render(wrapper.status_code, body, format)
|
|
28
|
+
end
|
|
16
29
|
end
|
|
17
30
|
end
|
|
31
|
+
|
|
32
|
+
if defined?(ActionDispatch::DebugExceptions)
|
|
33
|
+
ActionDispatch::DebugExceptions.prepend InertiaRails::InertiaDebugExceptions
|
|
34
|
+
end
|
data/lib/patches/mapper.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module InertiaRails
|
|
2
4
|
module InertiaMapper
|
|
3
5
|
def inertia(*args, **options)
|
|
@@ -12,7 +14,10 @@ module InertiaRails
|
|
|
12
14
|
if path.is_a?(Hash)
|
|
13
15
|
path.first
|
|
14
16
|
elsif resource_scope?
|
|
15
|
-
[path,
|
|
17
|
+
[path,
|
|
18
|
+
InertiaRails.configuration.component_path_resolver(
|
|
19
|
+
path: [@scope[:module], @scope[:controller]].compact.join('/'), action: path
|
|
20
|
+
)]
|
|
16
21
|
elsif @scope[:module].blank?
|
|
17
22
|
[path, path]
|
|
18
23
|
else
|
data/lib/patches/request.rb
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
namespace :inertia_rails do
|
|
2
4
|
namespace :install do
|
|
3
|
-
desc
|
|
4
|
-
task :
|
|
5
|
+
desc 'Installs inertia_rails packages and configurations for a React based app'
|
|
6
|
+
task react: :environment do
|
|
5
7
|
system 'rails g inertia_rails:install --front_end react'
|
|
6
8
|
end
|
|
7
|
-
desc
|
|
9
|
+
desc 'Installs inertia_rails packages and configurations for a Vue based app'
|
|
8
10
|
task vue: :environment do
|
|
9
11
|
system 'rails g inertia_rails:install --front_end vue'
|
|
10
12
|
end
|
|
11
|
-
desc
|
|
13
|
+
desc 'Installs inertia_rails packages and configurations for a Svelte based app'
|
|
12
14
|
task svelte: :environment do
|
|
13
15
|
system 'rails g inertia_rails:install --front_end svelte'
|
|
14
16
|
end
|
|
15
17
|
end
|
|
16
|
-
end
|
|
18
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: inertia_rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.12.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brian Knoles
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
- Eugene Granovsky
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2025-
|
|
12
|
+
date: 2025-11-09 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: railties
|
|
@@ -229,13 +229,14 @@ files:
|
|
|
229
229
|
- lib/inertia_rails/meta_tag_builder.rb
|
|
230
230
|
- lib/inertia_rails/middleware.rb
|
|
231
231
|
- lib/inertia_rails/optional_prop.rb
|
|
232
|
+
- lib/inertia_rails/prop_mergeable.rb
|
|
232
233
|
- lib/inertia_rails/renderer.rb
|
|
233
234
|
- lib/inertia_rails/rspec.rb
|
|
235
|
+
- lib/inertia_rails/scroll_metadata.rb
|
|
236
|
+
- lib/inertia_rails/scroll_prop.rb
|
|
234
237
|
- lib/inertia_rails/version.rb
|
|
235
238
|
- lib/patches/better_errors.rb
|
|
236
239
|
- lib/patches/debug_exceptions.rb
|
|
237
|
-
- lib/patches/debug_exceptions/patch-5-0.rb
|
|
238
|
-
- lib/patches/debug_exceptions/patch-5-1.rb
|
|
239
240
|
- lib/patches/mapper.rb
|
|
240
241
|
- lib/patches/request.rb
|
|
241
242
|
- lib/tasks/inertia_rails.rake
|
|
@@ -1,27 +0,0 @@
|
|
|
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
|
|
@@ -1,30 +0,0 @@
|
|
|
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
|