Skip to content

Commit 0875d68

Browse files
committed
Add support for :if, :unless, :only, :except options in inertia_share
1 parent 56dfc76 commit 0875d68

File tree

4 files changed

+115
-4
lines changed

4 files changed

+115
-4
lines changed

lib/inertia_rails/controller.rb

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,19 @@ module Controller
1414
end
1515

1616
module ClassMethods
17-
def inertia_share(attrs = {}, &block)
18-
@inertia_share ||= []
19-
@inertia_share << attrs.freeze unless attrs.empty?
20-
@inertia_share << block if block
17+
def inertia_share(hash = nil, **props, &block)
18+
options = extract_inertia_share_options(props)
19+
return push_to_inertia_share(**(hash || props), &block) if options.empty?
20+
21+
push_to_inertia_share do
22+
next unless options[:if].all? { |filter| instance_exec(&filter) } if options[:if]
23+
next unless options[:unless].none? { |filter| instance_exec(&filter) } if options[:unless]
24+
25+
next hash unless block
26+
27+
res = instance_exec(&block)
28+
hash ? hash.merge(res) : res
29+
end
2130
end
2231

2332
def inertia_config(**attrs)
@@ -55,6 +64,53 @@ def _inertia_shared_data
5564
end.freeze
5665
end
5766
end
67+
68+
private
69+
70+
def push_to_inertia_share(**attrs, &block)
71+
@inertia_share ||= []
72+
@inertia_share << attrs.freeze unless attrs.empty?
73+
@inertia_share << block if block
74+
end
75+
76+
def extract_inertia_share_options(props)
77+
options = props.slice(:if, :unless, :only, :except)
78+
79+
return options if options.empty?
80+
81+
if props.except(:if, :unless, :only, :except).any?
82+
raise ArgumentError, "You must not mix shared data and [:if, :unless, :only, :except] options, pass data as a hash or a block."
83+
end
84+
85+
extract_inertia_share_option(options, :only, :if)
86+
extract_inertia_share_option(options, :except, :unless)
87+
88+
options.transform_values! do |filters|
89+
Array(filters).map!(&method(:filter_to_proc))
90+
end
91+
92+
options
93+
end
94+
95+
def extract_inertia_share_option(options, from, to)
96+
if (from_value = options.delete(from))
97+
filter = AbstractController::Callbacks::ActionFilter.new([:inertia_share], from, from_value)
98+
options[to] = Array(options[to]).unshift(filter)
99+
end
100+
end
101+
102+
def filter_to_proc(filter)
103+
case filter
104+
when Symbol
105+
-> { send(filter) }
106+
when Proc
107+
filter
108+
when AbstractController::Callbacks::ActionFilter
109+
-> { filter.match?(self) }
110+
else
111+
raise ArgumentError, "You must pass a symbol or a proc as a filter."
112+
end
113+
end
58114
end
59115

60116
def default_render

spec/dummy/app/controllers/inertia_conditional_sharing_controller.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@ class InertiaConditionalSharingController < ApplicationController
77
{conditionally_shared_show_prop: 1} if action_name == "show"
88
end
99

10+
inertia_share only: :edit do
11+
{only_block_prop: 1}
12+
end
13+
14+
inertia_share except: [:show, :index] do
15+
{except_block_prop: 1}
16+
end
17+
18+
inertia_share if: -> { is_edit? } do
19+
{if_proc_prop: 1}
20+
end
21+
22+
inertia_share unless: -> { !is_edit? } do
23+
{unless_proc_prop: 1}
24+
end
25+
26+
inertia_share({only_prop: 1}, only: :edit)
27+
28+
inertia_share({if_prop: 1}, if: [:is_edit?, -> { true }])
29+
30+
inertia_share({unless_prop: 1}, unless: :not_edit?)
31+
32+
inertia_share({only_if_prop: 1}, only: :edit, if: -> { true })
33+
34+
inertia_share({except_if_prop: 1}, except: [:index, :show], if: -> { true })
35+
1036
def index
1137
render inertia: 'EmptyTestComponent', props: {
1238
index_only_prop: 1,
@@ -25,9 +51,23 @@ def show_with_a_problem
2551
}
2652
end
2753

54+
def edit
55+
render inertia: 'EmptyTestComponent', props: {
56+
edit_only_prop: 1,
57+
}
58+
end
59+
2860
protected
2961

3062
def conditionally_share_a_prop
3163
self.class.inertia_share incorrectly_conditionally_shared_prop: 1
3264
end
65+
66+
def not_edit?
67+
!is_edit?
68+
end
69+
70+
def is_edit?
71+
action_name == "edit"
72+
end
3373
end

spec/dummy/config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,6 @@
5252

5353
get 'conditional_share_index' => 'inertia_conditional_sharing#index'
5454
get 'conditional_share_show' => 'inertia_conditional_sharing#show'
55+
get 'conditional_share_edit' => 'inertia_conditional_sharing#edit'
5556
get 'conditional_share_show_with_a_problem' => 'inertia_conditional_sharing#show_with_a_problem'
5657
end

spec/inertia/conditional_sharing_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,20 @@
1414
expect(JSON.parse(response.body)['props'].deep_symbolize_keys).not_to include({
1515
conditionally_shared_show_prop: 1,
1616
})
17+
get conditional_share_edit_path, headers: { 'X-Inertia' => true }
18+
expect(JSON.parse(response.body)['props'].deep_symbolize_keys).to eq({
19+
normal_shared_prop: 1,
20+
only_block_prop: 1,
21+
except_block_prop: 1,
22+
if_proc_prop: 1,
23+
unless_proc_prop: 1,
24+
only_prop: 1,
25+
if_prop: 1,
26+
unless_prop: 1,
27+
only_if_prop: 1,
28+
except_if_prop: 1,
29+
edit_only_prop: 1,
30+
})
1731
end
1832
end
1933

0 commit comments

Comments
 (0)