Skip to content

Commit 54f3e11

Browse files
committed
Check for local key literals in controllers
1 parent 6c39739 commit 54f3e11

File tree

4 files changed

+94
-11
lines changed

4 files changed

+94
-11
lines changed

lib/rubocop/cop/github/rails_controller_render_literal.rb

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ class RailsControllerRenderLiteral < Cop
5454
def on_send(node)
5555
return unless render?(node)
5656

57-
if render_literal?(node) || render_view_component?(node) || render_const?(node)
57+
return if render_view_component?(node) || render_const?(node)
58+
59+
if render_literal?(node)
5860
elsif option_pairs = render_with_options?(node)
5961
option_pairs = option_pairs.reject { |pair| options_key?(pair) }
6062

@@ -65,18 +67,40 @@ def on_send(node)
6567
if template_node = option_pairs.map { |pair| template_key?(pair) }.compact.first
6668
if !literal?(template_node)
6769
add_offense(node, location: :expression)
70+
return
6871
end
6972
else
7073
add_offense(node, location: :expression)
74+
return
7175
end
7276

7377
if layout_node = option_pairs.map { |pair| layout_key?(pair) }.compact.first
7478
if !literal?(layout_node)
7579
add_offense(node, location: :expression)
80+
return
7681
end
7782
end
7883
else
7984
add_offense(node, location: :expression)
85+
return
86+
end
87+
88+
if render_literal?(node)
89+
option_hash = node.arguments[1]
90+
if option_hash && !option_hash.hash_type?
91+
add_offense(node, location: :expression)
92+
return
93+
end
94+
option_pairs = option_hash && option_hash.pairs
95+
else
96+
option_pairs = node.arguments[0].pairs
97+
end
98+
99+
if option_pairs
100+
locals = option_pairs.map { |pair| locals_key?(pair) }.compact.first
101+
if locals && (!locals.hash_type? || !hash_with_literal_keys?(locals))
102+
add_offense(node, location: :expression)
103+
end
80104
end
81105
end
82106
end

lib/rubocop/cop/github/rails_view_render_literal.rb

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,6 @@ class RailsViewRenderLiteral < Cop
1717
}) $_)
1818
PATTERN
1919

20-
def_node_matcher :locals_key?, <<-PATTERN
21-
(pair (sym {
22-
:locals
23-
}) $_)
24-
PATTERN
25-
2620
def_node_matcher :partial_key?, <<-PATTERN
2721
(pair (sym {
2822
:file
@@ -32,10 +26,6 @@ class RailsViewRenderLiteral < Cop
3226
}) $_)
3327
PATTERN
3428

35-
def hash_with_literal_keys?(hash)
36-
hash.pairs.all? { |pair| literal?(pair.key) }
37-
end
38-
3929
def on_send(node)
4030
return unless render?(node)
4131

lib/rubocop/cop/github/render_literal_helpers.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ module RenderLiteralHelpers
3636
(send nil? {:render :render_to_string} (send _ :with_collection ...) ...)
3737
PATTERN
3838

39+
def_node_matcher :locals_key?, <<-PATTERN
40+
(pair (sym :locals) $_)
41+
PATTERN
42+
43+
def hash_with_literal_keys?(hash)
44+
hash.pairs.all? { |pair| literal?(pair.key) }
45+
end
46+
3947
def render_view_component?(node)
4048
render_view_component_instance?(node) ||
4149
render_view_component_collection?(node)

test/test_rails_controller_render_literal.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,4 +393,65 @@ def index
393393
assert_equal 1, cop.offenses.count
394394
assert_equal "render must be used with a string literal or an instance of a Class", cop.offenses[0].message
395395
end
396+
397+
def test_render_shorthand_static_locals_no_offsense
398+
investigate cop, <<-RUBY, "app/controllers/products_controller.rb"
399+
class ProductsController < ActionController::Base
400+
def index
401+
render "products/index", locals: { product: product }
402+
end
403+
end
404+
RUBY
405+
406+
assert_equal 0, cop.offenses.count
407+
end
408+
409+
def test_render_partial_static_locals_no_offsense
410+
investigate cop, <<-RUBY, "app/controllers/products_controller.rb"
411+
class ProductsController < ActionController::Base
412+
def index
413+
render partial: "products/index", locals: { product: product }
414+
end
415+
end
416+
RUBY
417+
418+
assert_equal 0, cop.offenses.count
419+
end
420+
421+
def test_render_literal_dynamic_options_offense
422+
investigate cop, <<-RUBY, "app/controllers/products_controller.rb"
423+
class ProductsController < ActionController::Base
424+
def index
425+
render "products/product", options
426+
end
427+
end
428+
RUBY
429+
430+
assert_equal 1, cop.offenses.count
431+
end
432+
433+
def test_render_literal_dynamic_locals_offense
434+
investigate cop, <<-RUBY, "app/controllers/products_controller.rb"
435+
class ProductsController < ActionController::Base
436+
def index
437+
render "products/product", locals: locals
438+
end
439+
end
440+
RUBY
441+
442+
assert_equal 1, cop.offenses.count
443+
end
444+
445+
446+
def test_render_literal_dynamic_local_key_offense
447+
investigate cop, <<-RUBY, "app/controllers/products_controller.rb"
448+
class ProductsController < ActionController::Base
449+
def index
450+
render "products/product", locals: { product_key => product }
451+
end
452+
end
453+
RUBY
454+
455+
assert_equal 1, cop.offenses.count
456+
end
396457
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