inertia_jb 0.3.0 → 0.3.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/README.md +1 -1
- data/lib/inertia_jb/helper.rb +46 -17
- data/lib/inertia_jb/version.rb +1 -1
- data/test/controller_test.rb +43 -2
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 37e2ba2d8b4c896a4a4f7f006aa32cbee162cc7b798a77e78daab8a305512c65
|
|
4
|
+
data.tar.gz: 7d1f22f9ba1596965f7d8fc52c7ccc3f7f7aae78d3a1093464b77791ed858a27
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 69f29e30c55a3efe39d54695948fec6de98ef96cf1a788dcb7806fb05186bc6e04f3f92cdb4ae5d175457489b042a1a3d5c8e692df2fdb07d7559d22f13edea3
|
|
7
|
+
data.tar.gz: c666ba929d8d67a7daaed36b39985ac9642b546d182dbccf30abc0281b5c115daef7f395157bbee6a0e35943c29cdb5b2ce84d07a528993d6ee528db0e269eea
|
data/README.md
CHANGED
|
@@ -90,7 +90,7 @@ On an **initial (non-XHR) page load** the `data-page` root element is wrapped in
|
|
|
90
90
|
a layout; Inertia (XHR) visits always return a bare JSON body with no layout.
|
|
91
91
|
|
|
92
92
|
The layout is chosen from inertia-rails' `config.layout`, matching
|
|
93
|
-
`InertiaRails::Renderer`'s own semantics
|
|
93
|
+
`InertiaRails::Renderer`'s own semantics.
|
|
94
94
|
|
|
95
95
|
|
|
96
96
|
## Templates and partials
|
data/lib/inertia_jb/helper.rb
CHANGED
|
@@ -4,49 +4,78 @@ module InertiaJb
|
|
|
4
4
|
# Optional syntax sugar available inside `.html.inertia` templates, so you can
|
|
5
5
|
# write `optional { ... }` instead of `InertiaRails.optional { ... }`.
|
|
6
6
|
#
|
|
7
|
-
# These
|
|
8
|
-
#
|
|
9
|
-
#
|
|
7
|
+
# These delegate to the +InertiaRails+ factory methods; the returned prop
|
|
8
|
+
# objects are resolved by +InertiaRails::PropsResolver+ when the page is built
|
|
9
|
+
# (respecting partial reloads, grouping, etc.).
|
|
10
|
+
#
|
|
11
|
+
# Every block is bound to the current view with {InertiaJb.bind_to_view} so
|
|
12
|
+
# that a lazy prop's block runs in the *same* context an eager prop would —
|
|
13
|
+
# see that method for why this matters.
|
|
10
14
|
module Helper
|
|
11
15
|
# Only fetched when explicitly requested in a partial reload.
|
|
12
16
|
def optional(&block)
|
|
13
|
-
::InertiaRails.optional(&block)
|
|
17
|
+
::InertiaRails.optional(&InertiaJb.bind_to_view(self, block))
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
# Always fetched, even when not requested in a partial reload.
|
|
17
21
|
def always(&block)
|
|
18
|
-
::InertiaRails.always(&block)
|
|
22
|
+
::InertiaRails.always(&InertiaJb.bind_to_view(self, block))
|
|
19
23
|
end
|
|
20
24
|
|
|
21
25
|
# Excluded from the initial load; fetched in a follow-up request.
|
|
22
|
-
def defer(
|
|
23
|
-
::InertiaRails.defer(
|
|
26
|
+
def defer(*args, **kwargs, &block)
|
|
27
|
+
::InertiaRails.defer(*args, **kwargs, &InertiaJb.bind_to_view(self, block))
|
|
24
28
|
end
|
|
25
29
|
|
|
26
30
|
# Infinite-scroll prop (accepts a paginator or explicit metadata).
|
|
27
|
-
def scroll(
|
|
28
|
-
::InertiaRails.scroll(
|
|
31
|
+
def scroll(*args, **kwargs, &block)
|
|
32
|
+
::InertiaRails.scroll(*args, **kwargs, &InertiaJb.bind_to_view(self, block))
|
|
29
33
|
end
|
|
30
34
|
|
|
31
35
|
# Merged with existing client-side data instead of replacing it.
|
|
32
|
-
def merge(
|
|
33
|
-
::InertiaRails.merge(
|
|
36
|
+
def merge(*args, **kwargs, &block)
|
|
37
|
+
::InertiaRails.merge(*args, **kwargs, &InertiaJb.bind_to_view(self, block))
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
# Deep-merged with existing client-side data.
|
|
37
|
-
def deep_merge(
|
|
38
|
-
::InertiaRails.deep_merge(
|
|
41
|
+
def deep_merge(*args, **kwargs, &block)
|
|
42
|
+
::InertiaRails.deep_merge(*args, **kwargs, &InertiaJb.bind_to_view(self, block))
|
|
39
43
|
end
|
|
40
44
|
|
|
41
45
|
# Sent once and cached client-side; skipped on later visits unless reset or expired.
|
|
42
|
-
def once(
|
|
43
|
-
::InertiaRails.once(
|
|
46
|
+
def once(*args, **kwargs, &block)
|
|
47
|
+
::InertiaRails.once(*args, **kwargs, &InertiaJb.bind_to_view(self, block))
|
|
44
48
|
end
|
|
45
49
|
|
|
46
50
|
# Server-side cached via Rails.cache; the block's result is stored as JSON
|
|
47
51
|
# and reused on subsequent requests until the cache expires.
|
|
48
|
-
def cache(
|
|
49
|
-
::InertiaRails.cache(
|
|
52
|
+
def cache(*args, **kwargs, &block)
|
|
53
|
+
::InertiaRails.cache(*args, **kwargs, &InertiaJb.bind_to_view(self, block))
|
|
50
54
|
end
|
|
51
55
|
end
|
|
56
|
+
|
|
57
|
+
# Binds a lazy-prop block to the view that declared it, so the block evaluates
|
|
58
|
+
# in the same view context as an eager prop.
|
|
59
|
+
#
|
|
60
|
+
# Eager props are evaluated while the +.inertia+ template renders, so their
|
|
61
|
+
# +render(partial: ...)+ is the *view* helper — it returns jb data and never
|
|
62
|
+
# touches +response_body+. Lazy props (+defer+/+optional+/+always+/...) are
|
|
63
|
+
# different: inertia-rails resolves them later via
|
|
64
|
+
# +controller.instance_exec(&block)+, i.e. in *controller* context, where the
|
|
65
|
+
# same +render(partial: ...)+ binds to +ActionController+'s +render+ and
|
|
66
|
+
# assigns +response_body+. inertia-rails then performs its own
|
|
67
|
+
# +render(json:)+, and the already-set +response_body+ raises
|
|
68
|
+
# +AbstractController::DoubleRenderError+.
|
|
69
|
+
#
|
|
70
|
+
# Wrapping the block in +view.instance_exec+ keeps every block — eager or
|
|
71
|
+
# lazy — running against the view, so +render+ behaves identically everywhere.
|
|
72
|
+
# Controller-exposed helpers still work in the view (e.g. +policy_scope+,
|
|
73
|
+
# +current_user+ via Pundit/Devise +helper_method+s); the only controller-only
|
|
74
|
+
# call that does not carry over is +render_to_string+ — use +render(partial:,
|
|
75
|
+
# formats: [:html])+ instead, which returns the same String in a view.
|
|
76
|
+
def self.bind_to_view(view, block)
|
|
77
|
+
return block if block.nil?
|
|
78
|
+
|
|
79
|
+
proc { view.instance_exec(&block) }
|
|
80
|
+
end
|
|
52
81
|
end
|
data/lib/inertia_jb/version.rb
CHANGED
data/test/controller_test.rb
CHANGED
|
@@ -34,6 +34,12 @@ class TestController < ActionController::Base
|
|
|
34
34
|
def cached
|
|
35
35
|
@call_count = 0
|
|
36
36
|
end
|
|
37
|
+
|
|
38
|
+
# lazy props (defer/optional) whose block renders a jb partial.
|
|
39
|
+
def lazy_partial
|
|
40
|
+
@author = { id: 42, name: "John" }
|
|
41
|
+
@comments = [{ body: "first" }, { body: "second" }]
|
|
42
|
+
end
|
|
37
43
|
end
|
|
38
44
|
|
|
39
45
|
class ControllerTest < ActionController::TestCase
|
|
@@ -55,7 +61,13 @@ class ControllerTest < ActionController::TestCase
|
|
|
55
61
|
"{ id: @id, stats: optional { { visits: 42 } }, feed: defer(group: :feed) { [1, 2, 3] } }",
|
|
56
62
|
"test/cached.html.inertia" =>
|
|
57
63
|
"{ flash: once { 'hello' }, " \
|
|
58
|
-
"report: cache('report', expires_in: 1.minute) { Time.current.to_f } }"
|
|
64
|
+
"report: cache('report', expires_in: 1.minute) { Time.current.to_f } }",
|
|
65
|
+
# A deferred/optional prop whose block renders a jb partial. The block is
|
|
66
|
+
# resolved by inertia-rails in controller context, so a bare `render` there
|
|
67
|
+
# would set response_body and collide with inertia's own render(json:).
|
|
68
|
+
"test/lazy_partial.html.inertia" =>
|
|
69
|
+
"{ deferredAuthor: defer { render(partial: 'authors/author', object: @author) }, " \
|
|
70
|
+
"optionalComments: optional { render(partial: 'comments/comment', collection: @comments) } }"
|
|
59
71
|
}.freeze
|
|
60
72
|
|
|
61
73
|
def setup
|
|
@@ -63,7 +75,7 @@ class ControllerTest < ActionController::TestCase
|
|
|
63
75
|
|
|
64
76
|
@routes = ActionDispatch::Routing::RouteSet.new
|
|
65
77
|
@routes.draw do
|
|
66
|
-
%i[index nested collection with_partial special cached].each do |action|
|
|
78
|
+
%i[index nested collection with_partial special cached lazy_partial].each do |action|
|
|
67
79
|
get action.to_s => "test##{action}"
|
|
68
80
|
end
|
|
69
81
|
end
|
|
@@ -190,6 +202,35 @@ class ControllerTest < ActionController::TestCase
|
|
|
190
202
|
refute page["props"].key?("flash"), "once prop should be absent when client reports it cached"
|
|
191
203
|
end
|
|
192
204
|
|
|
205
|
+
# ---- lazy props that render jb partials ---------------------------------
|
|
206
|
+
|
|
207
|
+
def test_deferred_prop_rendering_jb_partial_does_not_double_render
|
|
208
|
+
inertia_get :lazy_partial,
|
|
209
|
+
headers: {
|
|
210
|
+
"X-Inertia-Partial-Component" => "test/lazy_partial",
|
|
211
|
+
"X-Inertia-Partial-Data" => "deferredAuthor"
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
assert_response :success
|
|
215
|
+
page = JSON.parse(response.body)
|
|
216
|
+
assert_equal({ "id" => 42, "name" => "John" }, page.dig("props", "deferredAuthor"))
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def test_optional_prop_rendering_jb_partial_does_not_double_render
|
|
220
|
+
inertia_get :lazy_partial,
|
|
221
|
+
headers: {
|
|
222
|
+
"X-Inertia-Partial-Component" => "test/lazy_partial",
|
|
223
|
+
"X-Inertia-Partial-Data" => "optionalComments"
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
assert_response :success
|
|
227
|
+
page = JSON.parse(response.body)
|
|
228
|
+
assert_equal(
|
|
229
|
+
[{ "body" => "first" }, { "body" => "second" }],
|
|
230
|
+
page.dig("props", "optionalComments")
|
|
231
|
+
)
|
|
232
|
+
end
|
|
233
|
+
|
|
193
234
|
# ---- cached props (server-cached) ---------------------------------------
|
|
194
235
|
|
|
195
236
|
def test_cached_prop_serves_same_value_across_requests
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: inertia_jb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- kikyous
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: inertia_rails
|