-
-
Notifications
You must be signed in to change notification settings - Fork 266
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new
Rails/MultipleRoutePaths
cop
This PR adds new `Rails/MultipleRoutePaths` cop that checks if mapping a route with multiple paths is deprecated and will be removed in Rails 8.1. ```ruby # bad get '/users', '/other_path', to: 'users#index' # good get '/users', to: 'users#index' get '/other_path', to: 'users#index' ``` This provides a migration path for the following warning added in rails/rails#52409. ```consle DEPRECATION WARNING: Mapping a route with multiple paths is deprecated and will be removed in Rails 8.1. Please use multiple method calls instead. ... ```
- Loading branch information
Showing
7 changed files
with
192 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* [#1407](https://github.com/rubocop/rubocop-rails/pull/1407): Add new `Rails/MultipleRoutePaths` cop. ([@koic][]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
# Common functionality for cops working with routes. | ||
module RoutesHelper | ||
extend NodePattern::Macros | ||
|
||
HTTP_METHODS = %i[get post put patch delete].freeze | ||
|
||
def_node_matcher :routes_draw?, <<~PATTERN | ||
(send (send _ :routes) :draw) | ||
PATTERN | ||
|
||
def within_routes?(node) | ||
node.each_ancestor(:block).any? { |block| routes_draw?(block.send_node) } | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Rails | ||
# Checks if mapping a route with multiple paths is deprecated and will be removed in Rails 8.1. | ||
# | ||
# @example | ||
# | ||
# # bad | ||
# get '/users', '/other_path', to: 'users#index' | ||
# | ||
# # good | ||
# get '/users', to: 'users#index' | ||
# get '/other_path', to: 'users#index' | ||
# | ||
class MultipleRoutePaths < Base | ||
include RoutesHelper | ||
extend AutoCorrector | ||
|
||
MSG = 'Use separate routes instead of combining multiple route paths in a single route.' | ||
RESTRICT_ON_SEND = HTTP_METHODS | ||
|
||
IGNORED_ARGUMENT_TYPES = %i[array hash].freeze | ||
|
||
def on_send(node) | ||
return unless within_routes?(node) | ||
|
||
route_paths = node.arguments.reject { |argument| IGNORED_ARGUMENT_TYPES.include?(argument.type) } | ||
return if route_paths.count < 2 | ||
|
||
add_offense(node) do |corrector| | ||
corrector.replace(node, migrate_to_multiple_routes(node, route_paths)) | ||
end | ||
end | ||
|
||
private | ||
|
||
def migrate_to_multiple_routes(node, route_paths) | ||
rest = route_paths.last.source_range.end.join(node.source_range.end).source | ||
indentation = ' ' * node.source_range.column | ||
|
||
route_paths.map do |route_path| | ||
"#{node.method_name} #{route_path.source}#{rest}" | ||
end.join("\n#{indentation}") | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::Cop::Rails::MultipleRoutePaths, :config do | ||
it 'registers an offense when using a route with multiple string route paths' do | ||
expect_offense(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get '/users', '/other_path/users', '/another_path/users' | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use separate routes instead of combining multiple route paths in a single route. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get '/users' | ||
get '/other_path/users' | ||
get '/another_path/users' | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when using a route with multiple route paths with option' do | ||
expect_offense(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get '/users', '/other_path/users', '/another_path/users', to: 'users#index' | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use separate routes instead of combining multiple route paths in a single route. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get '/users', to: 'users#index' | ||
get '/other_path/users', to: 'users#index' | ||
get '/another_path/users', to: 'users#index' | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when using a route with multiple route paths with splat option' do | ||
expect_offense(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get '/users', '/other_path/users', '/another_path/users', **options | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use separate routes instead of combining multiple route paths in a single route. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get '/users', **options | ||
get '/other_path/users', **options | ||
get '/another_path/users', **options | ||
end | ||
RUBY | ||
end | ||
|
||
it 'registers an offense when using a route with multiple symbol route paths' do | ||
expect_offense(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get :resend, :generate_new_password | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use separate routes instead of combining multiple route paths in a single route. | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get :resend | ||
get :generate_new_password | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when using single string path method calls' do | ||
expect_no_offenses(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get '/users' | ||
get '/other_path/users' | ||
get '/another_path/users' | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when using single string path with option method calls' do | ||
expect_no_offenses(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get '/users', to: 'users#index' | ||
get '/other_path/users', to: 'users#index' | ||
get '/another_path/users', to: 'users#index' | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when using single string path with array literal' do | ||
expect_no_offenses(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get '/other_path/users', [] | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when using single route path with no arguments' do | ||
expect_no_offenses(<<~RUBY) | ||
Rails.application.routes.draw do | ||
get | ||
end | ||
RUBY | ||
end | ||
|
||
it 'does not register an offense when not within routes' do | ||
expect_no_offenses(<<~RUBY) | ||
get '/users', '/other_path/users', '/another_path/users' | ||
RUBY | ||
end | ||
end |