Skip to content

Commit ab2ae71

Browse files
committed
Add merge strategies support
1 parent 291d0d2 commit ab2ae71

File tree

6 files changed

+78
-30
lines changed

6 files changed

+78
-30
lines changed

lib/inertia_rails/defer_prop.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ module InertiaRails
44
class DeferProp < IgnoreOnFirstLoadProp
55
DEFAULT_GROUP = 'default'
66

7-
attr_reader :group
7+
attr_reader :group, :merge_strategy
88

9-
def initialize(group: nil, merge: nil, deep_merge: nil, &block)
9+
def initialize(group: nil, merge: nil, deep_merge: nil, merge_strategy: nil, &block)
1010
raise ArgumentError, 'Cannot set both `deep_merge` and `merge` to true' if deep_merge && merge
1111

1212
super(&block)
1313

1414
@group = group || DEFAULT_GROUP
1515
@merge = merge || deep_merge
1616
@deep_merge = deep_merge
17+
@merge_strategy = merge_strategy
1718
end
1819

1920
def merge?

lib/inertia_rails/inertia_rails.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ def always(&block)
3333
AlwaysProp.new(&block)
3434
end
3535

36-
def merge(&block)
37-
MergeProp.new(&block)
36+
def merge(merge_strategy: nil, &block)
37+
MergeProp.new(merge_strategy: merge_strategy, &block)
3838
end
3939

40-
def deep_merge(&block)
41-
MergeProp.new(deep_merge: true, &block)
40+
def deep_merge(merge_strategy: nil, &block)
41+
MergeProp.new(deep_merge: true, merge_strategy: merge_strategy, &block)
4242
end
4343

44-
def defer(group: nil, merge: nil, deep_merge: nil, &block)
45-
DeferProp.new(group: group, merge: merge, deep_merge: deep_merge, &block)
44+
def defer(group: nil, merge: nil, deep_merge: nil, merge_strategy: nil, &block)
45+
DeferProp.new(group: group, merge: merge, deep_merge: deep_merge, merge_strategy: merge_strategy, &block)
4646
end
4747
end
4848
end

lib/inertia_rails/merge_prop.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22

33
module InertiaRails
44
class MergeProp < BaseProp
5-
def initialize(deep_merge: false, &block)
5+
attr_reader :merge_strategy
6+
7+
def initialize(deep_merge: false, merge_strategy: nil, &block)
68
super(&block)
79
@deep_merge = deep_merge
10+
@merge_strategy = merge_strategy
811
end
912

1013
def merge?

lib/inertia_rails/renderer.rb

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,17 @@ def page
106106
deferred_props = deferred_props_keys
107107
default_page[:deferredProps] = deferred_props if deferred_props.present?
108108

109-
all_merge_props = merge_props_keys
109+
deep_merge_props, merge_props = all_merge_props.partition do |_key, prop|
110+
prop.deep_merge?
111+
end
110112

111-
deep_merge_props, merge_props = all_merge_props.partition do |key|
112-
@props[key].deep_merge?
113+
merge_strategies = all_merge_props.filter_map do |key, prop|
114+
"#{key}.#{prop.merge_strategy}" if prop.merge_strategy
113115
end
114116

115-
default_page[:mergeProps] = merge_props if merge_props.present?
116-
default_page[:deepMergeProps] = deep_merge_props if deep_merge_props.present?
117+
default_page[:mergeProps] = merge_props.map(&:first) if merge_props.present?
118+
default_page[:deepMergeProps] = deep_merge_props.map(&:first) if deep_merge_props.present?
119+
default_page[:mergeStrategies] = merge_strategies if merge_strategies.present?
117120

118121
default_page
119122
end
@@ -147,9 +150,16 @@ def deferred_props_keys
147150
end
148151
end
149152

150-
def merge_props_keys
151-
@props.each_with_object([]) do |(key, prop), result|
152-
result << key if prop.try(:merge?) && reset_keys.exclude?(key)
153+
def all_merge_props
154+
@all_merge_props ||= @props.select do |key, prop|
155+
next unless prop.try(:merge?)
156+
next if reset_keys.include?(key)
157+
next if rendering_partial_component? && (
158+
(partial_keys.present? && partial_keys.exclude?(key.name)) ||
159+
(partial_except_keys.present? && partial_except_keys.include?(key.name))
160+
)
161+
162+
true
153163
end
154164
end
155165

@@ -180,7 +190,7 @@ def resolve_component(component)
180190
def keep_prop?(prop, path)
181191
return true if prop.is_a?(AlwaysProp)
182192

183-
if rendering_partial_component?
193+
if rendering_partial_component? && (partial_keys.present? || partial_except_keys.present?)
184194
path_with_prefixes = path_prefixes(path)
185195
return false if excluded_by_only_partial_keys?(path_with_prefixes)
186196
return false if excluded_by_except_partial_keys?(path_with_prefixes)

spec/dummy/app/controllers/inertia_render_test_controller.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,14 @@ def always_props
106106
def merge_props
107107
render inertia: 'TestComponent', props: {
108108
merge: InertiaRails.merge { 'merge prop' },
109+
merge_strategy: InertiaRails.merge(merge_strategy: 'id') { [id: 1] },
109110
deep_merge: InertiaRails.deep_merge { { deep: 'merge prop' } },
111+
deep_merge_strategy: InertiaRails.deep_merge(merge_strategy: 'deep.id') { { deep: [id: 1] } },
110112
regular: 'regular prop',
111113
deferred_merge: InertiaRails.defer(merge: true) { 'deferred and merge prop' },
114+
deferred_merge_strategy: InertiaRails.defer(merge: true, merge_strategy: 'id') { [id: 1] },
112115
deferred_deep_merge: InertiaRails.defer(deep_merge: true) { { deep: 'deferred and merge prop' } },
116+
deferred_deep_merge_strategy: InertiaRails.defer(deep_merge: true, merge_strategy: 'deep.id') { { deep: [id: 1] } },
113117
deferred: InertiaRails.defer { 'deferred' },
114118
}
115119
end

spec/inertia/rendering_spec.rb

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -530,30 +530,37 @@
530530
before { get merge_props_path, headers: headers }
531531

532532
it 'returns non-optional props and meta on first load' do
533-
expect(response.parsed_body['props']).to eq('merge' => 'merge prop', 'deep_merge' => { 'deep' => 'merge prop' },
534-
'regular' => 'regular prop')
535-
expect(response.parsed_body['mergeProps']).to match_array(%w[merge deferred_merge])
536-
expect(response.parsed_body['deepMergeProps']).to match_array(%w[deep_merge deferred_deep_merge])
537-
expect(response.parsed_body['deferredProps']).to eq('default' => %w[deferred_merge deferred_deep_merge deferred])
533+
expect(response.parsed_body['props']).to eq(
534+
'merge' => 'merge prop', 'merge_strategy' => [{ 'id' => 1 }],
535+
'deep_merge' => { 'deep' => 'merge prop' }, 'deep_merge_strategy' => { 'deep' => [{ 'id' => 1 }] },
536+
'regular' => 'regular prop'
537+
)
538+
expect(response.parsed_body['mergeProps']).to match_array(%w[merge merge_strategy deferred_merge deferred_merge_strategy])
539+
expect(response.parsed_body['deepMergeProps']).to match_array(%w[deep_merge deep_merge_strategy deferred_deep_merge deferred_deep_merge_strategy])
540+
expect(response.parsed_body['deferredProps']).to eq('default' => %w[deferred_merge deferred_merge_strategy deferred_deep_merge deferred_deep_merge_strategy deferred])
541+
expect(response.parsed_body['mergeStrategies']).to match_array(%w[deep_merge_strategy.deep.id deferred_deep_merge_strategy.deep.id deferred_merge_strategy.id merge_strategy.id])
538542
end
539543

540544
context 'with a partial reload' do
541545
let(:headers) do
542546
{
543547
'X-Inertia' => true,
544-
'X-Inertia-Partial-Data' => 'deferred_merge,deferred_deep_merge',
548+
'X-Inertia-Partial-Data' => 'deferred_merge,deferred_deep_merge,deferred_deep_merge_strategy,deferred_merge_strategy',
545549
'X-Inertia-Partial-Component' => 'TestComponent',
546550
}
547551
end
548552

549-
it 'returns listed and merge props' do
553+
it 'returns listed merge props' do
550554
expect(response.parsed_body['props']).to eq(
551555
'deferred_merge' => 'deferred and merge prop',
552-
'deferred_deep_merge' => { 'deep' => 'deferred and merge prop' }
556+
'deferred_deep_merge' => { 'deep' => 'deferred and merge prop' },
557+
'deferred_deep_merge_strategy' => { 'deep' => [{ 'id' => 1 }] },
558+
'deferred_merge_strategy' => [{ 'id' => 1 }]
553559
)
554-
expect(response.parsed_body['mergeProps']).to match_array(%w[merge deferred_merge])
555-
expect(response.parsed_body['deepMergeProps']).to match_array(%w[deep_merge deferred_deep_merge])
560+
expect(response.parsed_body['mergeProps']).to match_array(%w[deferred_merge deferred_merge_strategy])
561+
expect(response.parsed_body['deepMergeProps']).to match_array(%w[deferred_deep_merge deferred_deep_merge_strategy])
556562
expect(response.parsed_body['deferredProps']).to be_nil
563+
expect(response.parsed_body['mergeStrategies']).to match_array(%w[deferred_deep_merge_strategy.deep.id deferred_merge_strategy.id])
557564
end
558565
end
559566

@@ -567,13 +574,36 @@
567574
}
568575
end
569576

570-
it 'returns listed and merge props' do
577+
it 'returns listed props' do
571578
expect(response.parsed_body['props']).to eq(
572579
'deferred_merge' => 'deferred and merge prop',
573580
'deferred_deep_merge' => { 'deep' => 'deferred and merge prop' }
574581
)
575-
expect(response.parsed_body['mergeProps']).to match_array(%w[merge])
582+
expect(response.parsed_body['mergeProps']).to be_nil
583+
expect(response.parsed_body['deferredProps']).to be_nil
584+
expect(response.parsed_body['mergeStrategies']).to be_nil
585+
end
586+
end
587+
588+
context 'with an except header' do
589+
let(:headers) do
590+
{
591+
'X-Inertia' => true,
592+
'X-Inertia-Partial-Data' => 'deferred_merge,deferred_deep_merge,deep_merge_strategy',
593+
'X-Inertia-Partial-Except' => 'deferred_merge',
594+
'X-Inertia-Partial-Component' => 'TestComponent',
595+
}
596+
end
597+
598+
it 'returns only the excepted props' do
599+
expect(response.parsed_body['props']).to eq(
600+
'deferred_deep_merge' => { 'deep' => 'deferred and merge prop' },
601+
'deep_merge_strategy' => { 'deep' => [{ 'id' => 1 }] }
602+
)
603+
expect(response.parsed_body['mergeProps']).to be_nil
604+
expect(response.parsed_body['deepMergeProps']).to match_array(%w[deferred_deep_merge deep_merge_strategy])
576605
expect(response.parsed_body['deferredProps']).to be_nil
606+
expect(response.parsed_body['mergeStrategies']).to match_array(%w[deep_merge_strategy.deep.id])
577607
end
578608
end
579609
end

0 commit comments

Comments
 (0)