Skip to content

Commit 7f5fbd9

Browse files
committed
Ensure locals are fixed
1 parent d910021 commit 7f5fbd9

File tree

2 files changed

+86
-6
lines changed

2 files changed

+86
-6
lines changed

lib/rubocop/cop/github/rails_view_render_literal.rb

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module RuboCop
66
module Cop
77
module GitHub
88
class RailsViewRenderLiteral < Cop
9-
MSG = "render must be used with a string literal or an instance of a Class"
9+
MSG = "render must be used with a literal template and use literals for locals keys"
1010

1111
def_node_matcher :literal?, <<-PATTERN
1212
({str sym true false nil?} ...)
@@ -20,11 +20,11 @@ class RailsViewRenderLiteral < Cop
2020
(send nil? {:render :render_to_string} ({str sym} $_) $...)
2121
PATTERN
2222

23-
def_node_matcher :render_inst?, <<-PATTERN
23+
def_node_matcher :render_view_component?, <<-PATTERN
2424
(send nil? {:render :render_to_string} (send _ :new ...) ...)
2525
PATTERN
2626

27-
def_node_matcher :render_collection?, <<-PATTERN
27+
def_node_matcher :render_view_component_collection?, <<-PATTERN
2828
(send nil? {:render :render_to_string} (send _ :with_collection ...) ...)
2929
PATTERN
3030

@@ -38,6 +38,12 @@ class RailsViewRenderLiteral < Cop
3838
}) $_)
3939
PATTERN
4040

41+
def_node_matcher :locals_key?, <<-PATTERN
42+
(pair (sym {
43+
:locals
44+
}) $_)
45+
PATTERN
46+
4147
def_node_matcher :partial_key?, <<-PATTERN
4248
(pair (sym {
4349
:file
@@ -47,10 +53,17 @@ class RailsViewRenderLiteral < Cop
4753
}) $_)
4854
PATTERN
4955

56+
def hash_with_literal_keys?(hash)
57+
hash.pairs.all? { |pair| literal?(pair.key) }
58+
end
59+
5060
def on_send(node)
5161
return unless render?(node)
5262

53-
if render_literal?(node) || render_inst?(node) || render_collection?(node)
63+
# Ignore "component"-style renders
64+
return if render_view_component?(node) || render_view_component_collection?(node)
65+
66+
if render_literal?(node)
5467
elsif option_pairs = render_with_options?(node)
5568
if option_pairs.any? { |pair| ignore_key?(pair) }
5669
return
@@ -59,12 +72,31 @@ def on_send(node)
5972
if partial_node = option_pairs.map { |pair| partial_key?(pair) }.compact.first
6073
if !literal?(partial_node)
6174
add_offense(node, location: :expression)
75+
return
6276
end
6377
else
6478
add_offense(node, location: :expression)
79+
return
6580
end
6681
else
6782
add_offense(node, location: :expression)
83+
return
84+
end
85+
86+
if render_literal?(node) && node.arguments.count > 1
87+
locals = node.arguments[1]
88+
elsif options_pairs = render_with_options?(node)
89+
locals = option_pairs.map { |pair| locals_key?(pair) }.compact.first
90+
end
91+
92+
if locals
93+
if locals.hash_type?
94+
if !hash_with_literal_keys?(locals)
95+
add_offense(node, location: :expression)
96+
end
97+
else
98+
add_offense(node, location: :expression)
99+
end
68100
end
69101
end
70102
end

test/test_rails_view_render_literal.rb

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def test_render_variable_offense
4343
ERB
4444

4545
assert_equal 2, cop.offenses.count
46-
assert_equal "render must be used with a string literal or an instance of a Class", cop.offenses[0].message
46+
assert_equal "render must be used with a literal template and use literals for locals keys", cop.offenses[0].message
4747
end
4848

4949
def test_render_component_no_offense
@@ -94,7 +94,7 @@ def test_render_layout_variable_literal_no_offense
9494
ERB
9595

9696
assert_equal 1, cop.offenses.count
97-
assert_equal "render must be used with a string literal or an instance of a Class", cop.offenses[0].message
97+
assert_equal "render must be used with a literal template and use literals for locals keys", cop.offenses[0].message
9898
end
9999

100100
def test_render_inline_no_offense
@@ -112,4 +112,52 @@ def test_render_template_literal_no_offense
112112

113113
assert_equal 0, cop.offenses.count
114114
end
115+
116+
def test_render_literal_static_locals_no_offense
117+
erb_investigate cop, <<-ERB, "app/views/products/index.html.erb"
118+
<%= render "products/product", product: product %>
119+
ERB
120+
121+
assert_equal 0, cop.offenses.count
122+
end
123+
124+
def test_render_literal_dynamic_locals_offense
125+
erb_investigate cop, <<-ERB, "app/views/products/index.html.erb"
126+
<%= render "products/product", locals %>
127+
ERB
128+
129+
assert_equal 1, cop.offenses.count
130+
end
131+
132+
def test_render_literal_dynamic_local_key_offense
133+
erb_investigate cop, <<-ERB, "app/views/products/index.html.erb"
134+
<%= render "products/product", { product_key => product } %>
135+
ERB
136+
137+
assert_equal 1, cop.offenses.count
138+
end
139+
140+
def test_render_options_static_locals_no_offense
141+
erb_investigate cop, <<-ERB, "app/views/products/index.html.erb"
142+
<%= render partial: "products/product", locals: { product: product } %>
143+
ERB
144+
145+
assert_equal 0, cop.offenses.count
146+
end
147+
148+
def test_render_options_dynamic_locals_offense
149+
erb_investigate cop, <<-ERB, "app/views/products/index.html.erb"
150+
<%= render partial: "products/product", locals: locals %>
151+
ERB
152+
153+
assert_equal 1, cop.offenses.count
154+
end
155+
156+
def test_render_options_dynamic_local_key_offense
157+
erb_investigate cop, <<-ERB, "app/views/products/index.html.erb"
158+
<%= render partial: "products/product", locals: { product_key => product } %>
159+
ERB
160+
161+
assert_equal 1, cop.offenses.count
162+
end
115163
end

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy