Skip to content

Commit 93eb1a3

Browse files
skryukovbknoles
authored andcommitted
Add InertiaRails.merge prop
1 parent 3bd6339 commit 93eb1a3

File tree

7 files changed

+101
-10
lines changed

7 files changed

+101
-10
lines changed

lib/inertia_rails/defer_prop.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
1+
# frozen_string_literal: true
2+
13
module InertiaRails
24
class DeferProp < IgnoreOnFirstLoadProp
3-
DEFAULT_GROUP = "default".freeze
5+
DEFAULT_GROUP = "default"
46

57
attr_reader :group
68

7-
def initialize(group: nil, &block)
9+
def initialize(group: nil, merge: nil, &block)
810
@group = group || DEFAULT_GROUP
11+
@merge = merge
912
@block = block
1013
end
14+
15+
def merge?
16+
@merge
17+
end
1118
end
1219
end

lib/inertia_rails/inertia_rails.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require 'inertia_rails/always_prop'
44
require 'inertia_rails/lazy_prop'
55
require 'inertia_rails/defer_prop'
6+
require 'inertia_rails/merge_prop'
67
require 'inertia_rails/configuration'
78

89
module InertiaRails
@@ -25,8 +26,12 @@ def always(&block)
2526
AlwaysProp.new(&block)
2627
end
2728

28-
def defer(group: nil, &block)
29-
DeferProp.new(group:, &block)
29+
def merge(&block)
30+
MergeProp.new(&block)
31+
end
32+
33+
def defer(group: nil, merge: nil, &block)
34+
DeferProp.new(group: group, merge: merge, &block)
3035
end
3136
end
3237
end

lib/inertia_rails/merge_prop.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# frozen_string_literal: true
2+
3+
module InertiaRails
4+
class MergeProp < BaseProp
5+
def initialize(*)
6+
super
7+
@merge = true
8+
end
9+
10+
def merge?
11+
@merge
12+
end
13+
end
14+
end

lib/inertia_rails/renderer.rb

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
require 'net/http'
44
require 'json'
5-
require_relative "inertia_rails"
5+
require_relative 'inertia_rails'
66

77
module InertiaRails
88
class Renderer
@@ -112,6 +112,9 @@ def page
112112
deferred_props = deferred_props_keys
113113
default_page[:deferredProps] = deferred_props if deferred_props.present?
114114

115+
merge_props = merge_props_keys
116+
default_page[:mergeProps] = merge_props if merge_props.present?
117+
115118
default_page
116119
end
117120

@@ -134,14 +137,25 @@ def deep_transform_props(props, parent_path = [], &block)
134137
def deferred_props_keys
135138
return if rendering_partial_component?
136139

137-
@props.select { |_, prop| prop.is_a?(DeferProp) }
138-
.map { |key, prop| { key: key, group: prop.group } }
139-
.group_by { |prop| prop[:group] }
140-
.transform_values { |props| props.map { |prop| prop[:key].to_s } }
140+
@props.each_with_object({}) do |(key, prop), result|
141+
(result[prop.group] ||= []) << key if prop.is_a?(DeferProp)
142+
end
143+
end
144+
145+
def merge_props_keys
146+
@props.each_with_object([]) do |(key, prop), result|
147+
if prop.try(:merge?) && reset_keys.exclude?(key)
148+
result << key
149+
end
150+
end
141151
end
142152

143153
def partial_keys
144-
(@request.headers['X-Inertia-Partial-Data'] || '').split(',').compact
154+
@partial_keys ||= (@request.headers['X-Inertia-Partial-Data'] || '').split(',').compact
155+
end
156+
157+
def reset_keys
158+
(@request.headers['X-Inertia-Reset'] || '').split(',').compact.map(&:to_sym)
145159
end
146160

147161
def partial_except_keys

spec/dummy/app/controllers/inertia_render_test_controller.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,15 @@ def always_props
9494
}
9595
end
9696

97+
def merge_props
98+
render inertia: 'TestComponent', props: {
99+
merge: InertiaRails.merge { 'merge prop' },
100+
regular: 'regular prop',
101+
deferred_merge: InertiaRails.defer(merge: true) { 'deferred and merge prop'},
102+
deferred: InertiaRails.defer { 'deferred' },
103+
}
104+
end
105+
97106
def deferred_props
98107
render inertia: 'TestComponent', props: {
99108
name: 'Brian',

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 'merge_props' => 'inertia_render_test#merge_props'
3637
get 'deferred_props' => 'inertia_render_test#deferred_props'
3738
get 'non_inertiafied' => 'inertia_test#non_inertiafied'
3839
get 'deeply_nested_props' => 'inertia_render_test#deeply_nested_props'

spec/inertia/rendering_spec.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,47 @@
394394
end
395395
end
396396

397+
context 'merged prop rendering' do
398+
let(:headers) { { 'X-Inertia' => true } }
399+
400+
before { get merge_props_path, headers: headers }
401+
402+
it 'returns non-optional props and meta on first load' do
403+
expect(response.parsed_body['props']).to eq('merge' => 'merge prop', 'regular' => 'regular prop')
404+
expect(response.parsed_body['mergeProps']).to match_array(%w[merge deferred_merge])
405+
expect(response.parsed_body['deferredProps']).to eq('default' => %w[deferred_merge deferred])
406+
end
407+
408+
context 'with a partial reload' do
409+
let(:headers) {{
410+
'X-Inertia' => true,
411+
'X-Inertia-Partial-Data' => 'deferred_merge',
412+
'X-Inertia-Partial-Component' => 'TestComponent',
413+
}}
414+
415+
it 'returns listed and merge props' do
416+
expect(response.parsed_body['props']).to eq({'deferred_merge' => 'deferred and merge prop'})
417+
expect(response.parsed_body['mergeProps']).to match_array(%w[merge deferred_merge])
418+
expect(response.parsed_body['deferredProps']).to be_nil
419+
end
420+
end
421+
422+
context 'with a reset header' do
423+
let(:headers) {{
424+
'X-Inertia' => true,
425+
'X-Inertia-Partial-Data' => 'deferred_merge',
426+
'X-Inertia-Partial-Component' => 'TestComponent',
427+
'X-Inertia-Reset' => 'deferred_merge'
428+
}}
429+
430+
it 'returns listed and merge props' do
431+
expect(response.parsed_body['props']).to eq({'deferred_merge' => 'deferred and merge prop'})
432+
expect(response.parsed_body['mergeProps']).to match_array(%w[merge])
433+
expect(response.parsed_body['deferredProps']).to be_nil
434+
end
435+
end
436+
end
437+
397438
context 'deferred prop rendering' do
398439
context 'on first load' do
399440
let (:page) {

0 commit comments

Comments
 (0)