rubocop-rails 2.19.1 → 2.30.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +70 -16
- data/config/default.yml +173 -28
- data/lib/rubocop/cop/mixin/active_record_helper.rb +16 -4
- data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +2 -2
- data/lib/rubocop/cop/mixin/database_type_resolvable.rb +66 -0
- data/lib/rubocop/cop/mixin/index_method.rb +68 -61
- data/lib/rubocop/cop/mixin/routes_helper.rb +20 -0
- data/lib/rubocop/cop/mixin/target_rails_version.rb +27 -2
- data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +3 -1
- data/lib/rubocop/cop/rails/action_controller_test_case.rb +2 -2
- data/lib/rubocop/cop/rails/action_filter.rb +3 -0
- data/lib/rubocop/cop/rails/action_order.rb +1 -5
- data/lib/rubocop/cop/rails/active_record_aliases.rb +2 -2
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +1 -5
- data/lib/rubocop/cop/rails/active_support_aliases.rb +6 -5
- data/lib/rubocop/cop/rails/active_support_on_load.rb +21 -1
- data/lib/rubocop/cop/rails/add_column_index.rb +1 -0
- data/lib/rubocop/cop/rails/after_commit_override.rb +1 -1
- data/lib/rubocop/cop/rails/application_record.rb +4 -0
- data/lib/rubocop/cop/rails/assert_not.rb +0 -1
- data/lib/rubocop/cop/rails/belongs_to.rb +1 -1
- data/lib/rubocop/cop/rails/blank.rb +1 -1
- data/lib/rubocop/cop/rails/bulk_change_table.rb +19 -45
- data/lib/rubocop/cop/rails/compact_blank.rb +29 -8
- data/lib/rubocop/cop/rails/content_tag.rb +2 -2
- data/lib/rubocop/cop/rails/dangerous_column_names.rb +448 -0
- data/lib/rubocop/cop/rails/date.rb +14 -5
- data/lib/rubocop/cop/rails/delegate.rb +53 -7
- data/lib/rubocop/cop/rails/duplicate_association.rb +71 -10
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +3 -3
- data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +2 -2
- data/lib/rubocop/cop/rails/enum_hash.rb +31 -8
- data/lib/rubocop/cop/rails/enum_syntax.rb +130 -0
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +29 -7
- data/lib/rubocop/cop/rails/env_local.rb +69 -0
- data/lib/rubocop/cop/rails/expanded_date_range.rb +1 -1
- data/lib/rubocop/cop/rails/file_path.rb +186 -18
- data/lib/rubocop/cop/rails/find_by.rb +3 -3
- data/lib/rubocop/cop/rails/find_by_id.rb +9 -23
- data/lib/rubocop/cop/rails/find_each.rb +1 -1
- data/lib/rubocop/cop/rails/freeze_time.rb +1 -1
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +1 -1
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +1 -1
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +7 -0
- data/lib/rubocop/cop/rails/http_status.rb +16 -5
- data/lib/rubocop/cop/rails/i18n_lazy_lookup.rb +63 -13
- data/lib/rubocop/cop/rails/i18n_locale_texts.rb +5 -1
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +23 -3
- data/lib/rubocop/cop/rails/index_by.rb +28 -12
- data/lib/rubocop/cop/rails/index_with.rb +28 -12
- data/lib/rubocop/cop/rails/inquiry.rb +2 -1
- data/lib/rubocop/cop/rails/inverse_of.rb +1 -1
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +19 -10
- data/lib/rubocop/cop/rails/link_to_blank.rb +2 -2
- data/lib/rubocop/cop/rails/match_route.rb +1 -9
- data/lib/rubocop/cop/rails/multiple_route_paths.rb +50 -0
- data/lib/rubocop/cop/rails/not_null_column.rb +100 -6
- data/lib/rubocop/cop/rails/output.rb +3 -2
- data/lib/rubocop/cop/rails/pick.rb +10 -5
- data/lib/rubocop/cop/rails/pluck.rb +21 -1
- data/lib/rubocop/cop/rails/pluck_id.rb +2 -1
- data/lib/rubocop/cop/rails/pluck_in_where.rb +35 -13
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +30 -16
- data/lib/rubocop/cop/rails/presence.rb +1 -1
- data/lib/rubocop/cop/rails/present.rb +1 -3
- data/lib/rubocop/cop/rails/rake_environment.rb +22 -6
- data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +190 -0
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
- data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +16 -0
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +2 -2
- data/lib/rubocop/cop/rails/reflection_class_name.rb +2 -2
- data/lib/rubocop/cop/rails/refute_methods.rb +0 -1
- data/lib/rubocop/cop/rails/relative_date_constant.rb +1 -1
- data/lib/rubocop/cop/rails/render_plain_text.rb +6 -3
- data/lib/rubocop/cop/rails/request_referer.rb +1 -1
- data/lib/rubocop/cop/rails/response_parsed_body.rb +52 -10
- data/lib/rubocop/cop/rails/reversible_migration.rb +7 -5
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +58 -15
- data/lib/rubocop/cop/rails/save_bang.rb +22 -14
- data/lib/rubocop/cop/rails/schema_comment.rb +17 -10
- data/lib/rubocop/cop/rails/select_map.rb +79 -0
- data/lib/rubocop/cop/rails/skips_model_validations.rb +9 -4
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +1 -2
- data/lib/rubocop/cop/rails/strip_heredoc.rb +1 -1
- data/lib/rubocop/cop/rails/strong_parameters_expect.rb +104 -0
- data/lib/rubocop/cop/rails/three_state_boolean_column.rb +4 -5
- data/lib/rubocop/cop/rails/time_zone.rb +26 -11
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +40 -9
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +11 -26
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +17 -21
- data/lib/rubocop/cop/rails/unknown_env.rb +5 -1
- data/lib/rubocop/cop/rails/unused_ignored_columns.rb +6 -0
- data/lib/rubocop/cop/rails/unused_render_content.rb +67 -0
- data/lib/rubocop/cop/rails/validation.rb +9 -4
- data/lib/rubocop/cop/rails/where_equals.rb +29 -12
- data/lib/rubocop/cop/rails/where_exists.rb +9 -9
- data/lib/rubocop/cop/rails/where_missing.rb +6 -2
- data/lib/rubocop/cop/rails/where_not.rb +18 -11
- data/lib/rubocop/cop/rails/where_range.rb +203 -0
- data/lib/rubocop/cop/rails_cops.rb +11 -0
- data/lib/rubocop/rails/migration_file_skippable.rb +54 -0
- data/lib/rubocop/rails/plugin.rb +48 -0
- data/lib/rubocop/rails/schema_loader/schema.rb +8 -7
- data/lib/rubocop/rails/schema_loader.rb +5 -15
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop/rails.rb +1 -8
- data/lib/rubocop-rails.rb +12 -4
- metadata +55 -11
- data/lib/rubocop/rails/inject.rb +0 -18
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# A mixin to extend cops in order to determine the database type.
|
6
|
+
#
|
7
|
+
# This module automatically detect an adapter from `development` environment
|
8
|
+
# in `config/database.yml` or the environment variable `DATABASE_URL`
|
9
|
+
# when the `Database` option is not set.
|
10
|
+
module DatabaseTypeResolvable
|
11
|
+
MYSQL = 'mysql'
|
12
|
+
POSTGRESQL = 'postgresql'
|
13
|
+
|
14
|
+
def database
|
15
|
+
cop_config['Database'] || database_from_yaml || database_from_env
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def database_from_yaml
|
21
|
+
return unless database_yaml
|
22
|
+
|
23
|
+
case database_adapter
|
24
|
+
when 'mysql2', 'trilogy'
|
25
|
+
MYSQL
|
26
|
+
when 'postgresql', 'postgis'
|
27
|
+
POSTGRESQL
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def database_from_env
|
32
|
+
url = ENV['DATABASE_URL'].presence
|
33
|
+
return unless url
|
34
|
+
|
35
|
+
case url
|
36
|
+
when %r{\A(mysql2|trilogy)://}
|
37
|
+
MYSQL
|
38
|
+
when %r{\Apostgres(ql)?://}
|
39
|
+
POSTGRESQL
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def database_yaml
|
44
|
+
return unless File.exist?('config/database.yml')
|
45
|
+
|
46
|
+
yaml = if YAML.respond_to?(:unsafe_load_file)
|
47
|
+
YAML.unsafe_load_file('config/database.yml')
|
48
|
+
else
|
49
|
+
YAML.load_file('config/database.yml')
|
50
|
+
end
|
51
|
+
return unless yaml.is_a? Hash
|
52
|
+
|
53
|
+
config = yaml['development']
|
54
|
+
return unless config.is_a?(Hash)
|
55
|
+
|
56
|
+
config
|
57
|
+
rescue Psych::SyntaxError
|
58
|
+
# noop
|
59
|
+
end
|
60
|
+
|
61
|
+
def database_adapter
|
62
|
+
database_yaml['adapter'] || database_yaml.first.last['adapter']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -6,7 +6,72 @@ module RuboCop
|
|
6
6
|
module IndexMethod # rubocop:disable Metrics/ModuleLength
|
7
7
|
RESTRICT_ON_SEND = %i[each_with_object to_h map collect []].freeze
|
8
8
|
|
9
|
-
|
9
|
+
# Internal helper class to hold match data
|
10
|
+
Captures = ::Struct.new(
|
11
|
+
:transformed_argname,
|
12
|
+
:transforming_body_expr
|
13
|
+
) do
|
14
|
+
def noop_transformation?
|
15
|
+
transforming_body_expr.lvar_type? && transforming_body_expr.children == [transformed_argname]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Internal helper class to hold autocorrect data
|
20
|
+
Autocorrection = ::Struct.new(:match, :block_node, :leading, :trailing) do
|
21
|
+
def self.from_each_with_object(node, match)
|
22
|
+
new(match, node, 0, 0)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.from_to_h(node, match)
|
26
|
+
new(match, node, 0, 0)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.from_map_to_h(node, match)
|
30
|
+
if node.block_literal?
|
31
|
+
strip_trailing_chars = 0
|
32
|
+
else
|
33
|
+
map_range = node.children.first.source_range
|
34
|
+
node_range = node.source_range
|
35
|
+
strip_trailing_chars = node_range.end_pos - map_range.end_pos
|
36
|
+
end
|
37
|
+
|
38
|
+
new(match, node.children.first, 0, strip_trailing_chars)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.from_hash_brackets_map(node, match)
|
42
|
+
new(match, node.children.last, "#{node.receiver.source}[".length, ']'.length)
|
43
|
+
end
|
44
|
+
|
45
|
+
def strip_prefix_and_suffix(node, corrector)
|
46
|
+
expression = node.source_range
|
47
|
+
corrector.remove_leading(expression, leading)
|
48
|
+
corrector.remove_trailing(expression, trailing)
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_new_method_name(new_method_name, corrector)
|
52
|
+
range = block_node.send_node.loc.selector
|
53
|
+
if (send_end = block_node.send_node.loc.end)
|
54
|
+
# If there are arguments (only true in the `each_with_object` case)
|
55
|
+
range = range.begin.join(send_end)
|
56
|
+
end
|
57
|
+
corrector.replace(range, new_method_name)
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_new_arg_name(transformed_argname, corrector)
|
61
|
+
return if block_node.numblock_type?
|
62
|
+
|
63
|
+
corrector.replace(block_node.arguments, "|#{transformed_argname}|")
|
64
|
+
end
|
65
|
+
|
66
|
+
def set_new_body_expression(transforming_body_expr, corrector)
|
67
|
+
body_source = transforming_body_expr.source
|
68
|
+
body_source = "{ #{body_source} }" if transforming_body_expr.hash_type? && !transforming_body_expr.braces?
|
69
|
+
|
70
|
+
corrector.replace(block_node.body, body_source)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def on_block(node)
|
10
75
|
on_bad_each_with_object(node) do |*match|
|
11
76
|
handle_possible_offense(node, match, 'each_with_object')
|
12
77
|
end
|
@@ -18,6 +83,8 @@ module RuboCop
|
|
18
83
|
end
|
19
84
|
end
|
20
85
|
|
86
|
+
alias on_numblock on_block
|
87
|
+
|
21
88
|
def on_send(node)
|
22
89
|
on_bad_map_to_h(node) do |*match|
|
23
90
|
handle_possible_offense(node, match, 'map { ... }.to_h')
|
@@ -100,66 +167,6 @@ module RuboCop
|
|
100
167
|
correction.set_new_arg_name(captures.transformed_argname, corrector)
|
101
168
|
correction.set_new_body_expression(captures.transforming_body_expr, corrector)
|
102
169
|
end
|
103
|
-
|
104
|
-
# Internal helper class to hold match data
|
105
|
-
Captures = Struct.new(
|
106
|
-
:transformed_argname,
|
107
|
-
:transforming_body_expr
|
108
|
-
) do
|
109
|
-
def noop_transformation?
|
110
|
-
transforming_body_expr.lvar_type? && transforming_body_expr.children == [transformed_argname]
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
# Internal helper class to hold autocorrect data
|
115
|
-
Autocorrection = Struct.new(:match, :block_node, :leading, :trailing) do
|
116
|
-
def self.from_each_with_object(node, match)
|
117
|
-
new(match, node, 0, 0)
|
118
|
-
end
|
119
|
-
|
120
|
-
def self.from_to_h(node, match)
|
121
|
-
new(match, node, 0, 0)
|
122
|
-
end
|
123
|
-
|
124
|
-
def self.from_map_to_h(node, match)
|
125
|
-
strip_trailing_chars = 0
|
126
|
-
|
127
|
-
unless node.parent&.block_type?
|
128
|
-
map_range = node.children.first.source_range
|
129
|
-
node_range = node.source_range
|
130
|
-
strip_trailing_chars = node_range.end_pos - map_range.end_pos
|
131
|
-
end
|
132
|
-
|
133
|
-
new(match, node.children.first, 0, strip_trailing_chars)
|
134
|
-
end
|
135
|
-
|
136
|
-
def self.from_hash_brackets_map(node, match)
|
137
|
-
new(match, node.children.last, "#{node.receiver.source}[".length, ']'.length)
|
138
|
-
end
|
139
|
-
|
140
|
-
def strip_prefix_and_suffix(node, corrector)
|
141
|
-
expression = node.source_range
|
142
|
-
corrector.remove_leading(expression, leading)
|
143
|
-
corrector.remove_trailing(expression, trailing)
|
144
|
-
end
|
145
|
-
|
146
|
-
def set_new_method_name(new_method_name, corrector)
|
147
|
-
range = block_node.send_node.loc.selector
|
148
|
-
if (send_end = block_node.send_node.loc.end)
|
149
|
-
# If there are arguments (only true in the `each_with_object` case)
|
150
|
-
range = range.begin.join(send_end)
|
151
|
-
end
|
152
|
-
corrector.replace(range, new_method_name)
|
153
|
-
end
|
154
|
-
|
155
|
-
def set_new_arg_name(transformed_argname, corrector)
|
156
|
-
corrector.replace(block_node.arguments, "|#{transformed_argname}|")
|
157
|
-
end
|
158
|
-
|
159
|
-
def set_new_body_expression(transforming_body_expr, corrector)
|
160
|
-
corrector.replace(block_node.body, transforming_body_expr.source)
|
161
|
-
end
|
162
|
-
end
|
163
170
|
end
|
164
171
|
end
|
165
172
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for cops working with routes.
|
6
|
+
module RoutesHelper
|
7
|
+
extend NodePattern::Macros
|
8
|
+
|
9
|
+
HTTP_METHODS = %i[get post put patch delete].freeze
|
10
|
+
|
11
|
+
def_node_matcher :routes_draw?, <<~PATTERN
|
12
|
+
(send (send _ :routes) :draw)
|
13
|
+
PATTERN
|
14
|
+
|
15
|
+
def within_routes?(node)
|
16
|
+
node.each_ancestor(:block).any? { |block| routes_draw?(block.send_node) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -4,12 +4,37 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
# Common functionality for checking target rails version.
|
6
6
|
module TargetRailsVersion
|
7
|
+
# Informs the base RuboCop gem that it the Rails version is checked via `requires_gem` API,
|
8
|
+
# without needing to call this `#support_target_rails_version` method.
|
9
|
+
USES_REQUIRES_GEM_API = true
|
10
|
+
# Look for `railties` instead of `rails`, to support apps that only use a subset of `rails`
|
11
|
+
# See https://github.com/rubocop/rubocop/pull/11289
|
12
|
+
TARGET_GEM_NAME = 'railties' # :nodoc:
|
13
|
+
|
7
14
|
def minimum_target_rails_version(version)
|
8
|
-
|
15
|
+
if respond_to?(:requires_gem)
|
16
|
+
case version
|
17
|
+
when Integer, Float then requires_gem(TARGET_GEM_NAME, ">= #{version}")
|
18
|
+
when String then requires_gem(TARGET_GEM_NAME, version)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
# Fallback path for previous versions of RuboCop which don't support the `requires_gem` API yet.
|
22
|
+
@minimum_target_rails_version = version
|
23
|
+
end
|
9
24
|
end
|
10
25
|
|
11
26
|
def support_target_rails_version?(version)
|
12
|
-
|
27
|
+
if respond_to?(:requires_gem)
|
28
|
+
return false unless gem_requirements
|
29
|
+
|
30
|
+
gem_requirement = gem_requirements[TARGET_GEM_NAME]
|
31
|
+
return true unless gem_requirement # If we have no requirement, then we support all versions
|
32
|
+
|
33
|
+
gem_requirement.satisfied_by?(Gem::Version.new(version))
|
34
|
+
else
|
35
|
+
# Fallback path for previous versions of RuboCop which don't support the `requires_gem` API yet.
|
36
|
+
@minimum_target_rails_version <= version
|
37
|
+
end
|
13
38
|
end
|
14
39
|
end
|
15
40
|
end
|
@@ -85,7 +85,7 @@ module RuboCop
|
|
85
85
|
|
86
86
|
def inherit_action_controller_base?(node)
|
87
87
|
class_node = find_ancestor(node, type: :class)
|
88
|
-
return unless class_node
|
88
|
+
return false unless class_node
|
89
89
|
|
90
90
|
action_controller?(class_node)
|
91
91
|
end
|
@@ -99,6 +99,8 @@ module RuboCop
|
|
99
99
|
|
100
100
|
def use_redirect_to?(context)
|
101
101
|
context.right_siblings.compact.any? do |sibling|
|
102
|
+
# Unwrap `return redirect_to :index`
|
103
|
+
sibling = sibling.children.first if sibling.return_type? && sibling.children.one?
|
102
104
|
sibling.send_type? && sibling.method?(:redirect_to)
|
103
105
|
end
|
104
106
|
end
|
@@ -3,8 +3,8 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
# Using `ActionController::TestCase
|
7
|
-
# `ActionDispatch::IntegrationTest
|
6
|
+
# Using `ActionController::TestCase` is discouraged and should be replaced by
|
7
|
+
# `ActionDispatch::IntegrationTest`. Controller tests are too close to the
|
8
8
|
# internals of a controller whereas integration tests mimic the browser/user.
|
9
9
|
#
|
10
10
|
# @safety
|
@@ -8,6 +8,9 @@ module RuboCop
|
|
8
8
|
# The cop is configurable and can enforce the use of the older
|
9
9
|
# something_filter methods or the newer something_action methods.
|
10
10
|
#
|
11
|
+
# IMPORTANT: This cop is deprecated. Because the `*_filter` methods were removed in Rails 4.2,
|
12
|
+
# and that Rails version is no longer supported by RuboCop Rails. This cop will be removed in RuboCop Rails 3.0.
|
13
|
+
#
|
11
14
|
# @example EnforcedStyle: action (default)
|
12
15
|
# # bad
|
13
16
|
# after_filter :do_stuff
|
@@ -92,11 +92,7 @@ module RuboCop
|
|
92
92
|
end
|
93
93
|
|
94
94
|
def range_with_comments(node)
|
95
|
-
|
96
|
-
# Using `RuboCop::Ext::Comment#source_range` requires RuboCop > 1.46,
|
97
|
-
# which introduces https://github.com/rubocop/rubocop/pull/11630.
|
98
|
-
ranges = [node, *processed_source.ast_with_comments[node]].map { |comment| comment.loc.expression }
|
99
|
-
# rubocop:enable InternalAffairs/LocationExpression
|
95
|
+
ranges = [node, *processed_source.ast_with_comments[node]].map(&:source_range)
|
100
96
|
ranges.reduce do |result, range|
|
101
97
|
add_range(result, range)
|
102
98
|
end
|
@@ -11,10 +11,10 @@ module RuboCop
|
|
11
11
|
# `update` but the method name remained same in the method definition.
|
12
12
|
#
|
13
13
|
# @example
|
14
|
-
# #bad
|
14
|
+
# # bad
|
15
15
|
# book.update_attributes!(author: 'Alice')
|
16
16
|
#
|
17
|
-
# #good
|
17
|
+
# # good
|
18
18
|
# book.update!(author: 'Alice')
|
19
19
|
class ActiveRecordAliases < Base
|
20
20
|
extend AutoCorrector
|
@@ -123,11 +123,7 @@ module RuboCop
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def inline_comment?(comment)
|
126
|
-
|
127
|
-
# Using `RuboCop::Ext::Comment#source_range` requires RuboCop > 1.46,
|
128
|
-
# which introduces https://github.com/rubocop/rubocop/pull/11630.
|
129
|
-
!comment_line?(comment.loc.expression.source_line)
|
130
|
-
# rubocop:enable InternalAffairs/LocationExpression
|
126
|
+
!comment_line?(comment.source_range.source_line)
|
131
127
|
end
|
132
128
|
|
133
129
|
def start_line_position(node)
|
@@ -27,13 +27,13 @@ module RuboCop
|
|
27
27
|
|
28
28
|
ALIASES = {
|
29
29
|
starts_with?: {
|
30
|
-
original: :start_with?, matcher: '(
|
30
|
+
original: :start_with?, matcher: '(call str :starts_with? _)'
|
31
31
|
},
|
32
32
|
ends_with?: {
|
33
|
-
original: :end_with?, matcher: '(
|
33
|
+
original: :end_with?, matcher: '(call str :ends_with? _)'
|
34
34
|
},
|
35
|
-
append: { original: :<<, matcher: '(
|
36
|
-
prepend: { original: :unshift, matcher: '(
|
35
|
+
append: { original: :<<, matcher: '(call array :append _)' },
|
36
|
+
prepend: { original: :unshift, matcher: '(call array :prepend _)' }
|
37
37
|
}.freeze
|
38
38
|
|
39
39
|
ALIASES.each do |aliased_method, options|
|
@@ -47,13 +47,14 @@ module RuboCop
|
|
47
47
|
preferred_method = ALIASES[aliased_method][:original]
|
48
48
|
message = format(MSG, prefer: preferred_method, current: aliased_method)
|
49
49
|
|
50
|
-
add_offense(node, message: message) do |corrector|
|
50
|
+
add_offense(node.loc.selector.join(node.source_range.end), message: message) do |corrector|
|
51
51
|
next if append(node)
|
52
52
|
|
53
53
|
corrector.replace(node.loc.selector, preferred_method)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
57
|
+
alias on_csend on_send
|
57
58
|
end
|
58
59
|
end
|
59
60
|
end
|
@@ -55,15 +55,35 @@ module RuboCop
|
|
55
55
|
'ActiveSupport::TestCase' => 'active_support_test_case'
|
56
56
|
}.freeze
|
57
57
|
|
58
|
+
RAILS_5_2_LOAD_HOOKS = {
|
59
|
+
'ActiveRecord::ConnectionAdapters::SQLite3Adapter' => 'active_record_sqlite3adapter'
|
60
|
+
}.freeze
|
61
|
+
|
62
|
+
RAILS_7_1_LOAD_HOOKS = {
|
63
|
+
'ActiveRecord::TestFixtures' => 'active_record_fixtures',
|
64
|
+
'ActiveModel::Model' => 'active_model',
|
65
|
+
'ActionText::EncryptedRichText' => 'action_text_encrypted_rich_text',
|
66
|
+
'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter' => 'active_record_postgresqladapter',
|
67
|
+
'ActiveRecord::ConnectionAdapters::Mysql2Adapter' => 'active_record_mysql2adapter',
|
68
|
+
'ActiveRecord::ConnectionAdapters::TrilogyAdapter' => 'active_record_trilogyadapter'
|
69
|
+
}.freeze
|
70
|
+
|
58
71
|
def on_send(node)
|
59
72
|
receiver, method, arguments = *node # rubocop:disable InternalAffairs/NodeDestructuring
|
60
|
-
return unless
|
73
|
+
return unless arguments && (hook = hook_for_const(receiver&.const_name))
|
61
74
|
|
62
75
|
preferred = "ActiveSupport.on_load(:#{hook}) { #{method} #{arguments.source} }"
|
63
76
|
add_offense(node, message: format(MSG, prefer: preferred, current: node.source)) do |corrector|
|
64
77
|
corrector.replace(node, preferred)
|
65
78
|
end
|
66
79
|
end
|
80
|
+
|
81
|
+
def hook_for_const(const_name)
|
82
|
+
hook = LOAD_HOOKS[const_name]
|
83
|
+
hook ||= RAILS_5_2_LOAD_HOOKS[const_name] if target_rails_version >= 5.2
|
84
|
+
hook ||= RAILS_7_1_LOAD_HOOKS[const_name] if target_rails_version >= 7.1
|
85
|
+
hook
|
86
|
+
end
|
67
87
|
end
|
68
88
|
end
|
69
89
|
end
|
@@ -48,7 +48,7 @@ module RuboCop
|
|
48
48
|
seen_callback_names = {}
|
49
49
|
|
50
50
|
each_after_commit_callback(class_node) do |node|
|
51
|
-
callback_name = node.
|
51
|
+
callback_name = node.first_argument.value
|
52
52
|
if seen_callback_names.key?(callback_name)
|
53
53
|
add_offense(node, message: format(MSG, name: callback_name))
|
54
54
|
else
|
@@ -5,6 +5,10 @@ module RuboCop
|
|
5
5
|
module Rails
|
6
6
|
# Checks that models subclass `ApplicationRecord` with Rails 5.0.
|
7
7
|
#
|
8
|
+
# It is a common practice to define models inside migrations in order to retain forward
|
9
|
+
# compatibility by avoiding loading any application code. And so migration files are excluded
|
10
|
+
# by default for this cop.
|
11
|
+
#
|
8
12
|
# @safety
|
9
13
|
# This cop's autocorrection is unsafe because it may let the logic from `ApplicationRecord`
|
10
14
|
# sneak into an Active Record model that is not purposed to inherit logic common among other
|
@@ -123,7 +123,7 @@ module RuboCop
|
|
123
123
|
def on_if(node)
|
124
124
|
return unless cop_config['UnlessPresent']
|
125
125
|
return unless node.unless?
|
126
|
-
return if node.else? && config.
|
126
|
+
return if node.else? && config.cop_enabled?('Style/UnlessElse')
|
127
127
|
|
128
128
|
unless_present?(node) do |method_call, receiver|
|
129
129
|
range = unless_condition(node, method_call)
|
@@ -12,8 +12,9 @@ module RuboCop
|
|
12
12
|
# The `bulk` option is only supported on the MySQL and
|
13
13
|
# the PostgreSQL (5.2 later) adapter; thus it will
|
14
14
|
# automatically detect an adapter from `development` environment
|
15
|
-
# in `config/database.yml`
|
16
|
-
#
|
15
|
+
# in `config/database.yml` or the environment variable `DATABASE_URL`
|
16
|
+
# when the `Database` option is not set.
|
17
|
+
# If the adapter is not `mysql2`, `trilogy`, `postgresql`, or `postgis`,
|
17
18
|
# this Cop ignores offenses.
|
18
19
|
#
|
19
20
|
# @example
|
@@ -63,6 +64,9 @@ module RuboCop
|
|
63
64
|
# end
|
64
65
|
# end
|
65
66
|
class BulkChangeTable < Base
|
67
|
+
include DatabaseTypeResolvable
|
68
|
+
include MigrationsHelper
|
69
|
+
|
66
70
|
MSG_FOR_CHANGE_TABLE = <<~MSG.chomp
|
67
71
|
You can combine alter queries using `bulk: true` options.
|
68
72
|
MSG
|
@@ -70,9 +74,6 @@ module RuboCop
|
|
70
74
|
You can use `change_table :%<table>s, bulk: true` to combine alter queries.
|
71
75
|
MSG
|
72
76
|
|
73
|
-
MYSQL = 'mysql'
|
74
|
-
POSTGRESQL = 'postgresql'
|
75
|
-
|
76
77
|
MIGRATION_METHODS = %i[change up down].freeze
|
77
78
|
|
78
79
|
COMBINABLE_TRANSFORMATIONS = %i[
|
@@ -113,8 +114,10 @@ module RuboCop
|
|
113
114
|
MYSQL_COMBINABLE_ALTER_METHODS = %i[rename_column add_index remove_index].freeze
|
114
115
|
|
115
116
|
POSTGRESQL_COMBINABLE_TRANSFORMATIONS = %i[change_default].freeze
|
117
|
+
POSTGRESQL_COMBINABLE_TRANSFORMATIONS_SINCE_6_1 = %i[change_null].freeze
|
116
118
|
|
117
119
|
POSTGRESQL_COMBINABLE_ALTER_METHODS = %i[change_column_default].freeze
|
120
|
+
POSTGRESQL_COMBINABLE_ALTER_METHODS_SINCE_6_1 = %i[change_column_null].freeze
|
118
121
|
|
119
122
|
def on_def(node)
|
120
123
|
return unless support_bulk_alter?
|
@@ -138,9 +141,9 @@ module RuboCop
|
|
138
141
|
return unless support_bulk_alter?
|
139
142
|
return unless node.command?(:change_table)
|
140
143
|
return if include_bulk_options?(node)
|
141
|
-
return unless node.block_node
|
144
|
+
return unless (body = node.block_node&.body)
|
142
145
|
|
143
|
-
send_nodes = send_nodes_from_change_table_block(
|
146
|
+
send_nodes = send_nodes_from_change_table_block(body)
|
144
147
|
|
145
148
|
add_offense_for_change_table(node) if count_transformations(send_nodes) > 1
|
146
149
|
end
|
@@ -174,39 +177,6 @@ module RuboCop
|
|
174
177
|
options.hash_type? && options.keys.any? { |key| key.sym_type? && key.value == :bulk }
|
175
178
|
end
|
176
179
|
|
177
|
-
def database
|
178
|
-
cop_config['Database'] || database_from_yaml
|
179
|
-
end
|
180
|
-
|
181
|
-
def database_from_yaml
|
182
|
-
return nil unless database_yaml
|
183
|
-
|
184
|
-
case database_yaml['adapter']
|
185
|
-
when 'mysql2'
|
186
|
-
MYSQL
|
187
|
-
when 'postgresql'
|
188
|
-
POSTGRESQL
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
def database_yaml
|
193
|
-
return nil unless File.exist?('config/database.yml')
|
194
|
-
|
195
|
-
yaml = if YAML.respond_to?(:unsafe_load_file)
|
196
|
-
YAML.unsafe_load_file('config/database.yml')
|
197
|
-
else
|
198
|
-
YAML.load_file('config/database.yml')
|
199
|
-
end
|
200
|
-
return nil unless yaml.is_a? Hash
|
201
|
-
|
202
|
-
config = yaml['development']
|
203
|
-
return nil unless config.is_a?(Hash)
|
204
|
-
|
205
|
-
config
|
206
|
-
rescue Psych::SyntaxError
|
207
|
-
nil
|
208
|
-
end
|
209
|
-
|
210
180
|
def support_bulk_alter?
|
211
181
|
case database
|
212
182
|
when MYSQL
|
@@ -229,7 +199,9 @@ module RuboCop
|
|
229
199
|
when MYSQL
|
230
200
|
COMBINABLE_ALTER_METHODS + MYSQL_COMBINABLE_ALTER_METHODS
|
231
201
|
when POSTGRESQL
|
232
|
-
COMBINABLE_ALTER_METHODS + POSTGRESQL_COMBINABLE_ALTER_METHODS
|
202
|
+
result = COMBINABLE_ALTER_METHODS + POSTGRESQL_COMBINABLE_ALTER_METHODS
|
203
|
+
result += POSTGRESQL_COMBINABLE_ALTER_METHODS_SINCE_6_1 if target_rails_version >= 6.1
|
204
|
+
result
|
233
205
|
end
|
234
206
|
end
|
235
207
|
|
@@ -238,14 +210,16 @@ module RuboCop
|
|
238
210
|
when MYSQL
|
239
211
|
COMBINABLE_TRANSFORMATIONS + MYSQL_COMBINABLE_TRANSFORMATIONS
|
240
212
|
when POSTGRESQL
|
241
|
-
COMBINABLE_TRANSFORMATIONS + POSTGRESQL_COMBINABLE_TRANSFORMATIONS
|
213
|
+
result = COMBINABLE_TRANSFORMATIONS + POSTGRESQL_COMBINABLE_TRANSFORMATIONS
|
214
|
+
result += POSTGRESQL_COMBINABLE_TRANSFORMATIONS_SINCE_6_1 if target_rails_version >= 6.1
|
215
|
+
result
|
242
216
|
end
|
243
217
|
end
|
244
218
|
|
245
219
|
# @param node [RuboCop::AST::SendNode]
|
246
220
|
def add_offense_for_alter_methods(node)
|
247
221
|
# arguments: [{(sym :table)(str "table")} ...]
|
248
|
-
table_node = node.
|
222
|
+
table_node = node.first_argument
|
249
223
|
return unless table_node.is_a? RuboCop::AST::BasicLiteralNode
|
250
224
|
|
251
225
|
message = format(MSG_FOR_ALTER_METHODS, table: table_node.value)
|
@@ -267,10 +241,10 @@ module RuboCop
|
|
267
241
|
# @param new_node [RuboCop::AST::SendNode]
|
268
242
|
def process(new_node)
|
269
243
|
# arguments: [{(sym :table)(str "table")} ...]
|
270
|
-
table_node = new_node.
|
244
|
+
table_node = new_node.first_argument
|
271
245
|
if table_node.is_a? RuboCop::AST::BasicLiteralNode
|
272
246
|
flush unless @nodes.all? do |node|
|
273
|
-
node.
|
247
|
+
node.first_argument.value.to_s == table_node.value.to_s
|
274
248
|
end
|
275
249
|
@nodes << new_node
|
276
250
|
else
|