Skip to content

Commit 3e00ec5

Browse files
committed
Add InertiaRails.deep_merge & InertiaRails.defer(deep_merge: true)
1 parent efc9ec8 commit 3e00ec5

File tree

8 files changed

+129
-17
lines changed

8 files changed

+129
-17
lines changed

lib/inertia_rails/defer_prop.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,22 @@ class DeferProp < IgnoreOnFirstLoadProp
66

77
attr_reader :group
88

9-
def initialize(group: nil, merge: nil, &block)
9+
def initialize(group: nil, merge: nil, deep_merge: nil, &block)
10+
raise ArgumentError, 'Cannot set both `deep_merge` and `merge` to true' if deep_merge && merge
11+
1012
super(&block)
1113

1214
@group = group || DEFAULT_GROUP
13-
@merge = merge
14-
@block = block
15+
@merge = merge || deep_merge
16+
@deep_merge = deep_merge
1517
end
1618

1719
def merge?
1820
@merge
1921
end
22+
23+
def deep_merge?
24+
@deep_merge
25+
end
2026
end
2127
end

lib/inertia_rails/inertia_rails.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@ def merge(&block)
3535
MergeProp.new(&block)
3636
end
3737

38-
def defer(group: nil, merge: nil, &block)
39-
DeferProp.new(group: group, merge: merge, &block)
38+
def deep_merge(&block)
39+
MergeProp.new(deep_merge: true, &block)
40+
end
41+
42+
def defer(group: nil, merge: nil, deep_merge: nil, &block)
43+
DeferProp.new(group: group, merge: merge, deep_merge: deep_merge, &block)
4044
end
4145
end
4246
end

lib/inertia_rails/merge_prop.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
module InertiaRails
44
class MergeProp < BaseProp
5-
def initialize(*)
6-
super
7-
@merge = true
5+
def initialize(deep_merge: false, &block)
6+
super(&block)
7+
@deep_merge = deep_merge
88
end
99

1010
def merge?
11-
@merge
11+
true
12+
end
13+
14+
def deep_merge?
15+
@deep_merge
1216
end
1317
end
1418
end

lib/inertia_rails/renderer.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,14 @@ def page
105105
deferred_props = deferred_props_keys
106106
default_page[:deferredProps] = deferred_props if deferred_props.present?
107107

108-
merge_props = merge_props_keys
108+
all_merge_props = merge_props_keys
109+
110+
deep_merge_props, merge_props = all_merge_props.partition do |key|
111+
@props[key].deep_merge?
112+
end
113+
109114
default_page[:mergeProps] = merge_props if merge_props.present?
115+
default_page[:deepMergeProps] = deep_merge_props if deep_merge_props.present?
110116

111117
default_page
112118
end

spec/dummy/app/controllers/inertia_render_test_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,10 @@ def always_props
105105
def merge_props
106106
render inertia: 'TestComponent', props: {
107107
merge: InertiaRails.merge { 'merge prop' },
108+
deep_merge: InertiaRails.deep_merge { {deep: 'merge prop'} },
108109
regular: 'regular prop',
109110
deferred_merge: InertiaRails.defer(merge: true) { 'deferred and merge prop' },
111+
deferred_deep_merge: InertiaRails.defer(deep_merge: true) { {deep: 'deferred and merge prop'} },
110112
deferred: InertiaRails.defer { 'deferred' },
111113
}
112114
end

spec/inertia/defer_prop_spec.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe InertiaRails::DeferProp do
4+
it_behaves_like 'base prop'
5+
6+
describe '#merge?' do
7+
subject(:merge?) { prop.merge? }
8+
9+
let(:prop) { described_class.new { 'block' } }
10+
11+
it { is_expected.to be_falsy }
12+
13+
context 'when merge is set' do
14+
let(:prop) { described_class.new(merge: true) { 'block' } }
15+
16+
it { is_expected.to be true }
17+
end
18+
19+
context 'when deep_merge is set' do
20+
let(:prop) { described_class.new(deep_merge: true) { 'block' } }
21+
22+
it { is_expected.to be true }
23+
end
24+
25+
context 'when both merge and deep_merge are set' do
26+
let(:prop) { described_class.new(merge: true, deep_merge: true) { 'block' } }
27+
28+
it 'raises an ArgumentError' do
29+
expect { merge? }.to raise_error(ArgumentError, 'Cannot set both `deep_merge` and `merge` to true')
30+
end
31+
end
32+
end
33+
34+
describe '#deep_merge?' do
35+
subject(:deep_merge?) { prop.deep_merge? }
36+
37+
let(:prop) { described_class.new { 'block' } }
38+
39+
it { is_expected.to be_falsy }
40+
41+
context 'when deep is true' do
42+
let(:prop) { described_class.new(deep_merge: true) { 'block' } }
43+
44+
it { is_expected.to be true }
45+
end
46+
end
47+
48+
describe '#group' do
49+
subject(:group) { prop.group }
50+
51+
let(:prop) { described_class.new { 'block' } }
52+
53+
it { is_expected.to eq('default') }
54+
55+
context 'when group is set' do
56+
let(:prop) { described_class.new(group: 'custom') { 'block' } }
57+
58+
it { is_expected.to eq('custom') }
59+
end
60+
end
61+
end

spec/inertia/merge_prop_spec.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe InertiaRails::MergeProp do
4+
it_behaves_like 'base prop'
5+
6+
describe '#merge?' do
7+
subject(:merge?) { prop.merge? }
8+
9+
let(:prop) { described_class.new { 'block' } }
10+
11+
it { is_expected.to be true }
12+
end
13+
14+
describe '#deep_merge?' do
15+
subject(:deep_merge?) { prop.deep_merge? }
16+
17+
let(:prop) { described_class.new { 'block' } }
18+
19+
it { is_expected.to be false }
20+
21+
context 'when deep_merge is true' do
22+
let(:prop) { described_class.new(deep_merge: true) { 'block' } }
23+
24+
it { is_expected.to be true }
25+
end
26+
end
27+
end

spec/inertia/rendering_spec.rb

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -513,23 +513,25 @@
513513
before { get merge_props_path, headers: headers }
514514

515515
it 'returns non-optional props and meta on first load' do
516-
expect(response.parsed_body['props']).to eq('merge' => 'merge prop', 'regular' => 'regular prop')
516+
expect(response.parsed_body['props']).to eq('merge' => 'merge prop', 'deep_merge' => { 'deep' => 'merge prop' }, 'regular' => 'regular prop')
517517
expect(response.parsed_body['mergeProps']).to match_array(%w[merge deferred_merge])
518-
expect(response.parsed_body['deferredProps']).to eq('default' => %w[deferred_merge deferred])
518+
expect(response.parsed_body['deepMergeProps']).to match_array(%w[deep_merge deferred_deep_merge])
519+
expect(response.parsed_body['deferredProps']).to eq('default' => %w[deferred_merge deferred_deep_merge deferred])
519520
end
520521

521522
context 'with a partial reload' do
522523
let(:headers) do
523524
{
524525
'X-Inertia' => true,
525-
'X-Inertia-Partial-Data' => 'deferred_merge',
526+
'X-Inertia-Partial-Data' => 'deferred_merge,deferred_deep_merge',
526527
'X-Inertia-Partial-Component' => 'TestComponent',
527528
}
528529
end
529530

530531
it 'returns listed and merge props' do
531-
expect(response.parsed_body['props']).to eq({ 'deferred_merge' => 'deferred and merge prop' })
532+
expect(response.parsed_body['props']).to eq({ 'deferred_merge' => 'deferred and merge prop', 'deferred_deep_merge' => { 'deep' => 'deferred and merge prop' } })
532533
expect(response.parsed_body['mergeProps']).to match_array(%w[merge deferred_merge])
534+
expect(response.parsed_body['deepMergeProps']).to match_array(%w[deep_merge deferred_deep_merge])
533535
expect(response.parsed_body['deferredProps']).to be_nil
534536
end
535537
end
@@ -538,14 +540,14 @@
538540
let(:headers) do
539541
{
540542
'X-Inertia' => true,
541-
'X-Inertia-Partial-Data' => 'deferred_merge',
543+
'X-Inertia-Partial-Data' => 'deferred_merge,deferred_deep_merge',
542544
'X-Inertia-Partial-Component' => 'TestComponent',
543-
'X-Inertia-Reset' => 'deferred_merge',
545+
'X-Inertia-Reset' => 'deferred_merge,deferred_deep_merge',
544546
}
545547
end
546548

547549
it 'returns listed and merge props' do
548-
expect(response.parsed_body['props']).to eq({ 'deferred_merge' => 'deferred and merge prop' })
550+
expect(response.parsed_body['props']).to eq({ 'deferred_merge' => 'deferred and merge prop', 'deferred_deep_merge' => { 'deep' => 'deferred and merge prop' } })
549551
expect(response.parsed_body['mergeProps']).to match_array(%w[merge])
550552
expect(response.parsed_body['deferredProps']).to be_nil
551553
end

0 commit comments

Comments
 (0)