Skip to content

Commit 3af4b7a

Browse files
PedroAugustoRamalhoDuarteskryukov
authored andcommitted
Add InertiaRails.defer prop
Co-authored-by: Svyatoslav Kryukov <[email protected]>
1 parent afec3b5 commit 3af4b7a

File tree

8 files changed

+95
-3
lines changed

8 files changed

+95
-3
lines changed

lib/inertia_rails/defer_prop.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module InertiaRails
2+
class DeferProp < IgnoreOnFirstLoadProp
3+
DEFAULT_GROUP = "default".freeze
4+
5+
attr_reader :group
6+
7+
def initialize(group: nil, &block)
8+
@group = group || DEFAULT_GROUP
9+
@block = block
10+
end
11+
end
12+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# frozen_string_literal: true
2+
3+
module InertiaRails
4+
class IgnoreOnFirstLoadProp < BaseProp
5+
end
6+
end

lib/inertia_rails/inertia_rails.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
require 'inertia_rails/base_prop'
2+
require 'inertia_rails/ignore_on_first_load_prop'
23
require 'inertia_rails/always_prop'
34
require 'inertia_rails/lazy_prop'
5+
require 'inertia_rails/defer_prop'
46
require 'inertia_rails/configuration'
57

68
module InertiaRails
@@ -22,5 +24,9 @@ def lazy(value = nil, &block)
2224
def always(&block)
2325
AlwaysProp.new(&block)
2426
end
27+
28+
def defer(group: nil, &block)
29+
DeferProp.new(group:, &block)
30+
end
2531
end
2632
end

lib/inertia_rails/lazy_prop.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
module InertiaRails
4-
class LazyProp < BaseProp
4+
class LazyProp < IgnoreOnFirstLoadProp
55
def initialize(value = nil, &block)
66
raise ArgumentError, 'You must provide either a value or a block, not both' if value && block
77

lib/inertia_rails/renderer.rb

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,17 @@ def computed_props
9696
end
9797

9898
def page
99-
{
99+
default_page = {
100100
component: component,
101101
props: computed_props,
102102
url: @request.original_fullpath,
103103
version: configuration.version,
104104
}
105+
106+
deferred_props = deferred_props_keys
107+
default_page[:deferredProps] = deferred_props if deferred_props.present?
108+
109+
default_page
105110
end
106111

107112
def deep_transform_props(props, parent_path = [], &block)
@@ -120,6 +125,15 @@ def deep_transform_props(props, parent_path = [], &block)
120125
end
121126
end
122127

128+
def deferred_props_keys
129+
return if rendering_partial_component?
130+
131+
@props.select { |_, prop| prop.is_a?(DeferProp) }
132+
.map { |key, prop| { key: key, group: prop.group } }
133+
.group_by { |prop| prop[:group] }
134+
.transform_values { |props| props.map { |prop| prop[:key].to_s } }
135+
end
136+
123137
def partial_keys
124138
(@request.headers['X-Inertia-Partial-Data'] || '').split(',').compact
125139
end
@@ -148,7 +162,7 @@ def keep_prop?(prop, path)
148162
end
149163

150164
# Precedence: Evaluate LazyProp only after partial keys have been checked
151-
return false if prop.is_a?(LazyProp) && !rendering_partial_component?
165+
return false if prop.is_a?(IgnoreOnFirstLoadProp) && !rendering_partial_component?
152166

153167
true
154168
end

spec/dummy/app/controllers/inertia_render_test_controller.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,15 @@ def always_props
9393
another_lazy: InertiaRails.lazy(->{ 'another lazy prop' })
9494
}
9595
end
96+
97+
def deferred_props
98+
render inertia: 'TestComponent', props: {
99+
name: 'Brian',
100+
sport: InertiaRails.defer(group: 'other') { 'basketball' },
101+
level: InertiaRails.defer do
102+
'worse than he believes'
103+
end,
104+
grit: InertiaRails.defer { 'intense' }
105+
}
106+
end
96107
end

spec/dummy/config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
get 'lazy_props' => 'inertia_render_test#lazy_props'
3434
get 'always_props' => 'inertia_render_test#always_props'
3535
get 'except_props' => 'inertia_render_test#except_props'
36+
get 'deferred_props' => 'inertia_render_test#deferred_props'
3637
get 'non_inertiafied' => 'inertia_test#non_inertiafied'
3738
get 'deeply_nested_props' => 'inertia_render_test#deeply_nested_props'
3839

spec/inertia/rendering_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,48 @@
393393
end
394394
end
395395
end
396+
397+
context 'deferred prop rendering' do
398+
context 'on first load' do
399+
let (:page) {
400+
InertiaRails::Renderer.new('TestComponent', controller, request, response, '', props: { name: 'Brian', sport: 'basketball', level: 'worse than he believes', grit: 'intense' }).send(:page)
401+
}
402+
let(:headers) { { 'X-Inertia' => true } }
403+
before { get deferred_props_path, headers: headers }
404+
405+
it "does not include defer props inside props in first load" do
406+
expect(JSON.parse(response.body)["props"]).to eq({ "name" => 'Brian' })
407+
end
408+
409+
it "returns deferredProps" do
410+
expect(JSON.parse(response.body)["deferredProps"]).to eq(
411+
"default" => ["level", "grit"],
412+
"other" => ["sport"]
413+
)
414+
end
415+
end
416+
417+
context 'with a partial reload' do
418+
let (:page) {
419+
InertiaRails::Renderer.new('TestComponent', controller, request, response, '', props: { sport: 'basketball', level: 'worse than he believes', grit: 'intense' }).send(:page)
420+
}
421+
let(:headers) { {
422+
'X-Inertia' => true,
423+
'X-Inertia-Partial-Data' => 'level,grit', # Simulate default group
424+
'X-Inertia-Partial-Component' => 'TestComponent',
425+
} }
426+
427+
before { get deferred_props_path, headers: headers }
428+
429+
it { is_expected.to eq page.to_json }
430+
it { is_expected.to include('intense') }
431+
it { is_expected.to include('worse') }
432+
it { is_expected.not_to include('basketball') }
433+
it "does not deferredProps key in json" do
434+
expect(JSON.parse(response.body)["deferredProps"]).to eq(nil)
435+
end
436+
end
437+
end
396438
end
397439

398440
def inertia_div(page)

0 commit comments

Comments
 (0)