rubocop-rails 2.22.1 → 2.24.1
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/README.md +7 -9
- data/config/default.yml +4 -2
- data/lib/rubocop/cop/mixin/active_record_helper.rb +15 -3
- data/lib/rubocop/cop/mixin/database_type_resolvable.rb +1 -1
- data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +2 -0
- data/lib/rubocop/cop/rails/active_record_aliases.rb +2 -2
- 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/after_commit_override.rb +1 -1
- data/lib/rubocop/cop/rails/bulk_change_table.rb +4 -4
- data/lib/rubocop/cop/rails/content_tag.rb +1 -1
- data/lib/rubocop/cop/rails/dangerous_column_names.rb +2 -3
- data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +2 -2
- data/lib/rubocop/cop/rails/expanded_date_range.rb +1 -1
- data/lib/rubocop/cop/rails/file_path.rb +5 -5
- 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/inquiry.rb +1 -0
- data/lib/rubocop/cop/rails/inverse_of.rb +1 -1
- data/lib/rubocop/cop/rails/pick.rb +6 -5
- data/lib/rubocop/cop/rails/pluck.rb +1 -1
- data/lib/rubocop/cop/rails/pluck_id.rb +2 -1
- data/lib/rubocop/cop/rails/pluck_in_where.rb +18 -5
- data/lib/rubocop/cop/rails/rake_environment.rb +2 -2
- data/lib/rubocop/cop/rails/redundant_active_record_all_method.rb +42 -30
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -1
- data/lib/rubocop/cop/rails/response_parsed_body.rb +52 -10
- data/lib/rubocop/cop/rails/reversible_migration.rb +3 -3
- data/lib/rubocop/cop/rails/save_bang.rb +6 -4
- data/lib/rubocop/cop/rails/time_zone.rb +2 -1
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +12 -4
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +1 -1
- data/lib/rubocop/cop/rails/unknown_env.rb +3 -3
- data/lib/rubocop/cop/rails/validation.rb +2 -2
- data/lib/rubocop/cop/rails/where_equals.rb +3 -2
- data/lib/rubocop/cop/rails/where_exists.rb +9 -8
- data/lib/rubocop/cop/rails/where_missing.rb +6 -2
- data/lib/rubocop/cop/rails/where_not.rb +8 -6
- data/lib/rubocop/rails/schema_loader/schema.rb +3 -2
- data/lib/rubocop/rails/schema_loader.rb +5 -15
- data/lib/rubocop/rails/version.rb +1 -1
- metadata +24 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee7d9bdd0fa7838d8bfecece133ccd92cc308603bcdf120c14224c5f2e312344
|
4
|
+
data.tar.gz: 7d740b495ffa368d26a73808af9adff990bb9c1d317d905f877b4f3e2025487c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98172f41e7b1aab55931f351757425815850809edd6fc4f5bc55c59271d9f12459ac51c2002e409534b623f321ab27798c32aaccb2d15d60c7bf309a9c044d58
|
7
|
+
data.tar.gz: c78e9a0d9e53e5203a2dd1846a79c3e9c7a16af69e98d94e6b7ae6358ae6a29b71c2ac3f09ddb2a9be06dc64097a736c3379730f50b9309c0e2ae084267aee70
|
data/README.md
CHANGED
@@ -66,17 +66,15 @@ end
|
|
66
66
|
## Rails configuration tip
|
67
67
|
|
68
68
|
If you are using Rails 6.1 or newer, add the following `config.generators.after_generate` setting to
|
69
|
-
your config/
|
69
|
+
your `config/environments/development.rb` to apply RuboCop autocorrection to code generated by `bin/rails g`.
|
70
70
|
|
71
71
|
```ruby
|
72
|
-
# config/
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
system("bundle exec rubocop -A --fail-level=E #{parsable_files.shelljoin}", exception: true)
|
79
|
-
end
|
72
|
+
# config/environments/development.rb
|
73
|
+
Rails.application.configure do
|
74
|
+
config.generators.after_generate do |files|
|
75
|
+
parsable_files = files.filter { |file| file.end_with?('.rb') }
|
76
|
+
unless parsable_files.empty?
|
77
|
+
system("bundle exec rubocop -A --fail-level=E #{parsable_files.shelljoin}", exception: true)
|
80
78
|
end
|
81
79
|
end
|
82
80
|
end
|
data/config/default.yml
CHANGED
@@ -165,6 +165,7 @@ Rails/ActiveSupportOnLoad:
|
|
165
165
|
- 'https://guides.rubyonrails.org/engines.html#available-load-hooks'
|
166
166
|
SafeAutoCorrect: false
|
167
167
|
VersionAdded: '2.16'
|
168
|
+
VersionChanged: '2.24'
|
168
169
|
|
169
170
|
Rails/AddColumnIndex:
|
170
171
|
Description: >-
|
@@ -445,9 +446,10 @@ Rails/EnvironmentVariableAccess:
|
|
445
446
|
# TODO: Set to `pending` status in RuboCop Rails 2 series when migration doc will be written.
|
446
447
|
Enabled: false
|
447
448
|
VersionAdded: '2.10'
|
448
|
-
VersionChanged: '2.
|
449
|
+
VersionChanged: '2.24'
|
449
450
|
Include:
|
450
451
|
- app/**/*.rb
|
452
|
+
- config/initializers/**/*.rb
|
451
453
|
- lib/**/*.rb
|
452
454
|
Exclude:
|
453
455
|
- lib/**/*.rake
|
@@ -902,7 +904,7 @@ Rails/RequireDependency:
|
|
902
904
|
VersionAdded: '2.10'
|
903
905
|
|
904
906
|
Rails/ResponseParsedBody:
|
905
|
-
Description: Prefer `response.parsed_body` to `
|
907
|
+
Description: Prefer `response.parsed_body` to custom parsing logic for `response.body`.
|
906
908
|
Enabled: pending
|
907
909
|
Safe: false
|
908
910
|
VersionAdded: '2.18'
|
@@ -39,7 +39,12 @@ module RuboCop
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def schema
|
42
|
-
RuboCop
|
42
|
+
# For compatibility with RuboCop 1.61.0 or lower.
|
43
|
+
if respond_to?(:parser_engine)
|
44
|
+
RuboCop::Rails::SchemaLoader.load(target_ruby_version, parser_engine)
|
45
|
+
else
|
46
|
+
RuboCop::Rails::SchemaLoader.load(target_ruby_version, :parser_whitequark)
|
47
|
+
end
|
43
48
|
end
|
44
49
|
|
45
50
|
def table_name(class_node)
|
@@ -98,8 +103,15 @@ module RuboCop
|
|
98
103
|
end
|
99
104
|
|
100
105
|
def in_where?(node)
|
101
|
-
send_node = node.each_ancestor(:send).first
|
102
|
-
|
106
|
+
send_node = node.each_ancestor(:send, :csend).first
|
107
|
+
return false unless send_node
|
108
|
+
|
109
|
+
return true if WHERE_METHODS.include?(send_node.method_name)
|
110
|
+
|
111
|
+
receiver = send_node.receiver
|
112
|
+
return false unless receiver&.send_type?
|
113
|
+
|
114
|
+
send_node.method?(:not) && WHERE_METHODS.include?(receiver.method_name)
|
103
115
|
end
|
104
116
|
end
|
105
117
|
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
|
@@ -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
|
@@ -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
|
@@ -14,7 +14,7 @@ module RuboCop
|
|
14
14
|
# automatically detect an adapter from `development` environment
|
15
15
|
# in `config/database.yml` or the environment variable `DATABASE_URL`
|
16
16
|
# when the `Database` option is not set.
|
17
|
-
# If the adapter is not `mysql2`, `trilogy`, or `
|
17
|
+
# If the adapter is not `mysql2`, `trilogy`, `postgresql`, or `postgis`,
|
18
18
|
# this Cop ignores offenses.
|
19
19
|
#
|
20
20
|
# @example
|
@@ -212,7 +212,7 @@ module RuboCop
|
|
212
212
|
# @param node [RuboCop::AST::SendNode]
|
213
213
|
def add_offense_for_alter_methods(node)
|
214
214
|
# arguments: [{(sym :table)(str "table")} ...]
|
215
|
-
table_node = node.
|
215
|
+
table_node = node.first_argument
|
216
216
|
return unless table_node.is_a? RuboCop::AST::BasicLiteralNode
|
217
217
|
|
218
218
|
message = format(MSG_FOR_ALTER_METHODS, table: table_node.value)
|
@@ -234,10 +234,10 @@ module RuboCop
|
|
234
234
|
# @param new_node [RuboCop::AST::SendNode]
|
235
235
|
def process(new_node)
|
236
236
|
# arguments: [{(sym :table)(str "table")} ...]
|
237
|
-
table_node = new_node.
|
237
|
+
table_node = new_node.first_argument
|
238
238
|
if table_node.is_a? RuboCop::AST::BasicLiteralNode
|
239
239
|
flush unless @nodes.all? do |node|
|
240
|
-
node.
|
240
|
+
node.first_argument.value.to_s == table_node.value.to_s
|
241
241
|
end
|
242
242
|
@nodes << new_node
|
243
243
|
else
|
@@ -7,7 +7,7 @@ module RuboCop
|
|
7
7
|
#
|
8
8
|
# NOTE: Allow `tag` when the first argument is a variable because
|
9
9
|
# `tag(name)` is simpler rather than `tag.public_send(name)`.
|
10
|
-
# And this cop will be renamed to something like `LegacyTag` in the future. (e.g. RuboCop Rails
|
10
|
+
# And this cop will be renamed to something like `LegacyTag` in the future. (e.g. RuboCop Rails 3.0)
|
11
11
|
#
|
12
12
|
# @example
|
13
13
|
# # bad
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
time
|
32
32
|
].to_set.freeze
|
33
33
|
|
34
|
-
# Generated from `ActiveRecord::AttributeMethods.dangerous_attribute_methods` on activerecord 7.1.
|
34
|
+
# Generated from `ActiveRecord::AttributeMethods.dangerous_attribute_methods` on activerecord 7.1.3.
|
35
35
|
# rubocop:disable Metrics/CollectionLiteralLength
|
36
36
|
DANGEROUS_COLUMN_NAMES = %w[
|
37
37
|
__callbacks
|
@@ -290,7 +290,6 @@ module RuboCop
|
|
290
290
|
new_record
|
291
291
|
no_touching
|
292
292
|
normalize_reflection_attribute
|
293
|
-
object_id
|
294
293
|
partial_inserts
|
295
294
|
partial_updates
|
296
295
|
perform_validations
|
@@ -428,7 +427,7 @@ module RuboCop
|
|
428
427
|
when :rename_column
|
429
428
|
node.arguments[2]
|
430
429
|
when *COLUMN_TYPE_METHOD_NAMES
|
431
|
-
node.
|
430
|
+
node.first_argument
|
432
431
|
end
|
433
432
|
end
|
434
433
|
|
@@ -14,10 +14,10 @@ module RuboCop
|
|
14
14
|
# when no output would be produced anyway.
|
15
15
|
#
|
16
16
|
# @example
|
17
|
-
# #bad
|
17
|
+
# # bad
|
18
18
|
# Rails.logger.debug "The time is #{Time.zone.now}."
|
19
19
|
#
|
20
|
-
# #good
|
20
|
+
# # good
|
21
21
|
# Rails.logger.debug { "The time is #{Time.zone.now}." }
|
22
22
|
#
|
23
23
|
class EagerEvaluationLogMessage < Base
|
@@ -51,7 +51,7 @@ module RuboCop
|
|
51
51
|
return if allow?(begin_node, end_node)
|
52
52
|
|
53
53
|
preferred_method = preferred_method(begin_node)
|
54
|
-
if begin_node.method?(:beginning_of_week) && begin_node.arguments.one?
|
54
|
+
if begin_node.method?(:beginning_of_week) && begin_node.arguments.one? && end_node.arguments.one?
|
55
55
|
return unless same_argument?(begin_node, end_node)
|
56
56
|
|
57
57
|
preferred_method << "(#{begin_node.first_argument.source})"
|
@@ -163,9 +163,9 @@ module RuboCop
|
|
163
163
|
|
164
164
|
def autocorrect_extension_after_rails_root_join_in_dstr(corrector, node, rails_root_index, extension_node)
|
165
165
|
rails_root_node = node.children[rails_root_index].children.first
|
166
|
-
return unless rails_root_node.
|
166
|
+
return unless rails_root_node.last_argument.str_type?
|
167
167
|
|
168
|
-
corrector.insert_before(rails_root_node.
|
168
|
+
corrector.insert_before(rails_root_node.last_argument.location.end, extension_node.source)
|
169
169
|
corrector.remove(extension_node)
|
170
170
|
end
|
171
171
|
|
@@ -174,7 +174,7 @@ module RuboCop
|
|
174
174
|
corrector.remove(
|
175
175
|
range_with_surrounding_space(
|
176
176
|
range_with_surrounding_comma(
|
177
|
-
node.
|
177
|
+
node.first_argument.source_range,
|
178
178
|
:right
|
179
179
|
),
|
180
180
|
side: :right
|
@@ -187,7 +187,7 @@ module RuboCop
|
|
187
187
|
end
|
188
188
|
|
189
189
|
def autocorrect_rails_root_join_with_string_arguments(corrector, node)
|
190
|
-
corrector.replace(node.
|
190
|
+
corrector.replace(node.first_argument, %("#{node.arguments.map(&:value).join('/')}"))
|
191
191
|
node.arguments[1..].each do |argument|
|
192
192
|
corrector.remove(
|
193
193
|
range_with_surrounding_comma(
|
@@ -221,7 +221,7 @@ module RuboCop
|
|
221
221
|
end
|
222
222
|
|
223
223
|
def append_argument(corrector, node, argument_source)
|
224
|
-
corrector.insert_after(node.
|
224
|
+
corrector.insert_after(node.last_argument, %(, "#{argument_source}"))
|
225
225
|
end
|
226
226
|
|
227
227
|
def replace_with_rails_root_join(corrector, node, argument_source)
|
@@ -28,7 +28,7 @@ module RuboCop
|
|
28
28
|
include RangeHelp
|
29
29
|
extend AutoCorrector
|
30
30
|
|
31
|
-
MSG = 'Use `find_by` instead of `where
|
31
|
+
MSG = 'Use `find_by` instead of `where%<dot>s%<method>s`.'
|
32
32
|
RESTRICT_ON_SEND = %i[first take].freeze
|
33
33
|
|
34
34
|
def on_send(node)
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
37
37
|
|
38
38
|
range = offense_range(node)
|
39
39
|
|
40
|
-
add_offense(range, message: format(MSG, method: node.method_name)) do |corrector|
|
40
|
+
add_offense(range, message: format(MSG, dot: node.loc.dot.source, method: node.method_name)) do |corrector|
|
41
41
|
autocorrect(corrector, node)
|
42
42
|
end
|
43
43
|
end
|
@@ -59,7 +59,7 @@ module RuboCop
|
|
59
59
|
return if node.method?(:first)
|
60
60
|
|
61
61
|
where_loc = node.receiver.loc.selector
|
62
|
-
first_loc = range_between(node.
|
62
|
+
first_loc = range_between(node.receiver.source_range.end_pos, node.loc.selector.end_pos)
|
63
63
|
|
64
64
|
corrector.replace(where_loc, 'find_by')
|
65
65
|
corrector.replace(first_loc, '')
|
@@ -24,40 +24,39 @@ module RuboCop
|
|
24
24
|
RESTRICT_ON_SEND = %i[take! find_by_id! find_by!].freeze
|
25
25
|
|
26
26
|
def_node_matcher :where_take?, <<~PATTERN
|
27
|
-
(
|
28
|
-
$(
|
27
|
+
(call
|
28
|
+
$(call _ :where
|
29
29
|
(hash
|
30
30
|
(pair (sym :id) $_))) :take!)
|
31
31
|
PATTERN
|
32
32
|
|
33
33
|
def_node_matcher :find_by?, <<~PATTERN
|
34
34
|
{
|
35
|
-
(
|
36
|
-
(
|
35
|
+
(call _ :find_by_id! $_)
|
36
|
+
(call _ :find_by! (hash (pair (sym :id) $_)))
|
37
37
|
}
|
38
38
|
PATTERN
|
39
39
|
|
40
40
|
def on_send(node)
|
41
41
|
where_take?(node) do |where, id_value|
|
42
42
|
range = where_take_offense_range(node, where)
|
43
|
-
bad_method = build_where_take_bad_method(id_value)
|
44
43
|
|
45
|
-
register_offense(range, id_value
|
44
|
+
register_offense(range, id_value)
|
46
45
|
end
|
47
46
|
|
48
47
|
find_by?(node) do |id_value|
|
49
48
|
range = find_by_offense_range(node)
|
50
|
-
bad_method = build_find_by_bad_method(node, id_value)
|
51
49
|
|
52
|
-
register_offense(range, id_value
|
50
|
+
register_offense(range, id_value)
|
53
51
|
end
|
54
52
|
end
|
53
|
+
alias on_csend on_send
|
55
54
|
|
56
55
|
private
|
57
56
|
|
58
|
-
def register_offense(range, id_value
|
57
|
+
def register_offense(range, id_value)
|
59
58
|
good_method = build_good_method(id_value)
|
60
|
-
message = format(MSG, good_method: good_method, bad_method:
|
59
|
+
message = format(MSG, good_method: good_method, bad_method: range.source)
|
61
60
|
|
62
61
|
add_offense(range, message: message) do |corrector|
|
63
62
|
corrector.replace(range, good_method)
|
@@ -75,19 +74,6 @@ module RuboCop
|
|
75
74
|
def build_good_method(id_value)
|
76
75
|
"find(#{id_value.source})"
|
77
76
|
end
|
78
|
-
|
79
|
-
def build_where_take_bad_method(id_value)
|
80
|
-
"where(id: #{id_value.source}).take!"
|
81
|
-
end
|
82
|
-
|
83
|
-
def build_find_by_bad_method(node, id_value)
|
84
|
-
case node.method_name
|
85
|
-
when :find_by_id!
|
86
|
-
"find_by_id!(#{id_value.source})"
|
87
|
-
when :find_by!
|
88
|
-
"find_by!(id: #{id_value.source})"
|
89
|
-
end
|
90
|
-
end
|
91
77
|
end
|
92
78
|
end
|
93
79
|
end
|
@@ -222,7 +222,7 @@ module RuboCop
|
|
222
222
|
|
223
223
|
def with_options_arguments(recv, node)
|
224
224
|
blocks = node.each_ancestor(:block).select do |block|
|
225
|
-
block.send_node.command?(:with_options) && same_context_in_with_options?(block.
|
225
|
+
block.send_node.command?(:with_options) && same_context_in_with_options?(block.first_argument, recv)
|
226
226
|
end
|
227
227
|
blocks.flat_map { |n| n.send_node.arguments }
|
228
228
|
end
|
@@ -28,13 +28,13 @@ module RuboCop
|
|
28
28
|
extend AutoCorrector
|
29
29
|
extend TargetRailsVersion
|
30
30
|
|
31
|
-
MSG = 'Prefer `pick(%<args>s)` over
|
31
|
+
MSG = 'Prefer `pick(%<args>s)` over `%<current>s`.'
|
32
32
|
RESTRICT_ON_SEND = %i[first].freeze
|
33
33
|
|
34
34
|
minimum_target_rails_version 6.0
|
35
35
|
|
36
36
|
def_node_matcher :pick_candidate?, <<~PATTERN
|
37
|
-
(
|
37
|
+
(call (call _ :pluck ...) :first)
|
38
38
|
PATTERN
|
39
39
|
|
40
40
|
def on_send(node)
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
node_selector = node.loc.selector
|
45
45
|
range = receiver_selector.join(node_selector)
|
46
46
|
|
47
|
-
add_offense(range, message: message(receiver)) do |corrector|
|
47
|
+
add_offense(range, message: message(receiver, range)) do |corrector|
|
48
48
|
first_range = receiver.source_range.end.join(node_selector)
|
49
49
|
|
50
50
|
corrector.remove(first_range)
|
@@ -52,11 +52,12 @@ module RuboCop
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
55
|
+
alias on_csend on_send
|
55
56
|
|
56
57
|
private
|
57
58
|
|
58
|
-
def message(receiver)
|
59
|
-
format(MSG, args: receiver.arguments.map(&:source).join(', '))
|
59
|
+
def message(receiver, current)
|
60
|
+
format(MSG, args: receiver.arguments.map(&:source).join(', '), current: current.source)
|
60
61
|
end
|
61
62
|
end
|
62
63
|
end
|
@@ -38,7 +38,7 @@ module RuboCop
|
|
38
38
|
minimum_target_rails_version 5.0
|
39
39
|
|
40
40
|
def_node_matcher :pluck_candidate?, <<~PATTERN
|
41
|
-
({block numblock} (
|
41
|
+
({block numblock} (call _ {:map :collect}) $_argument (send lvar :[] $_key))
|
42
42
|
PATTERN
|
43
43
|
|
44
44
|
def on_block(node)
|
@@ -34,7 +34,7 @@ module RuboCop
|
|
34
34
|
RESTRICT_ON_SEND = %i[pluck].freeze
|
35
35
|
|
36
36
|
def_node_matcher :pluck_id_call?, <<~PATTERN
|
37
|
-
(
|
37
|
+
(call _ :pluck {(sym :id) (send nil? :primary_key)})
|
38
38
|
PATTERN
|
39
39
|
|
40
40
|
def on_send(node)
|
@@ -47,6 +47,7 @@ module RuboCop
|
|
47
47
|
corrector.replace(offense_range(node), 'ids')
|
48
48
|
end
|
49
49
|
end
|
50
|
+
alias on_csend on_send
|
50
51
|
|
51
52
|
private
|
52
53
|
|
@@ -22,10 +22,13 @@ module RuboCop
|
|
22
22
|
# @example
|
23
23
|
# # bad
|
24
24
|
# Post.where(user_id: User.active.pluck(:id))
|
25
|
+
# Post.where(user_id: User.active.ids)
|
26
|
+
# Post.where.not(user_id: User.active.pluck(:id))
|
25
27
|
#
|
26
28
|
# # good
|
27
29
|
# Post.where(user_id: User.active.select(:id))
|
28
30
|
# Post.where(user_id: active_users.select(:id))
|
31
|
+
# Post.where.not(user_id: active_users.select(:id))
|
29
32
|
#
|
30
33
|
# @example EnforcedStyle: conservative (default)
|
31
34
|
# # good
|
@@ -40,8 +43,9 @@ module RuboCop
|
|
40
43
|
include ConfigurableEnforcedStyle
|
41
44
|
extend AutoCorrector
|
42
45
|
|
43
|
-
|
44
|
-
|
46
|
+
MSG_SELECT = 'Use `select` instead of `pluck` within `where` query method.'
|
47
|
+
MSG_IDS = 'Use `select(:id)` instead of `ids` within `where` query method.'
|
48
|
+
RESTRICT_ON_SEND = %i[pluck ids].freeze
|
45
49
|
|
46
50
|
def on_send(node)
|
47
51
|
return unless in_where?(node)
|
@@ -49,17 +53,26 @@ module RuboCop
|
|
49
53
|
|
50
54
|
range = node.loc.selector
|
51
55
|
|
52
|
-
|
53
|
-
|
56
|
+
if node.method?(:ids)
|
57
|
+
replacement = 'select(:id)'
|
58
|
+
message = MSG_IDS
|
59
|
+
else
|
60
|
+
replacement = 'select'
|
61
|
+
message = MSG_SELECT
|
62
|
+
end
|
63
|
+
|
64
|
+
add_offense(range, message: message) do |corrector|
|
65
|
+
corrector.replace(range, replacement)
|
54
66
|
end
|
55
67
|
end
|
68
|
+
alias on_csend on_send
|
56
69
|
|
57
70
|
private
|
58
71
|
|
59
72
|
def root_receiver(node)
|
60
73
|
receiver = node.receiver
|
61
74
|
|
62
|
-
if receiver&.
|
75
|
+
if receiver&.call_type?
|
63
76
|
root_receiver(receiver)
|
64
77
|
else
|
65
78
|
receiver
|
@@ -72,7 +72,7 @@ module RuboCop
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def task_name(node)
|
75
|
-
first_arg = node.
|
75
|
+
first_arg = node.first_argument
|
76
76
|
case first_arg&.type
|
77
77
|
when :sym, :str
|
78
78
|
first_arg.value.to_sym
|
@@ -97,7 +97,7 @@ module RuboCop
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def with_dependencies?(node)
|
100
|
-
first_arg = node.
|
100
|
+
first_arg = node.first_argument
|
101
101
|
return false unless first_arg
|
102
102
|
|
103
103
|
if first_arg.hash_type?
|
@@ -3,8 +3,43 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
+
# TODO: In the future, please support only RuboCop 1.52+ and use `RuboCop::Cop::AllowedReceivers`:
|
7
|
+
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cop/mixin/allowed_receivers.rb
|
8
|
+
# At that time, this duplicated module implementation can be removed.
|
9
|
+
module AllowedReceivers
|
10
|
+
def allowed_receiver?(receiver)
|
11
|
+
receiver_name = receiver_name(receiver)
|
12
|
+
|
13
|
+
allowed_receivers.include?(receiver_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def receiver_name(receiver)
|
17
|
+
return receiver_name(receiver.receiver) if receiver.receiver && !receiver.receiver.const_type?
|
18
|
+
|
19
|
+
if receiver.send_type?
|
20
|
+
if receiver.receiver
|
21
|
+
"#{receiver_name(receiver.receiver)}.#{receiver.method_name}"
|
22
|
+
else
|
23
|
+
receiver.method_name.to_s
|
24
|
+
end
|
25
|
+
else
|
26
|
+
receiver.source
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def allowed_receivers
|
31
|
+
cop_config.fetch('AllowedReceivers', [])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
6
35
|
# Detect redundant `all` used as a receiver for Active Record query methods.
|
7
36
|
#
|
37
|
+
# For the methods `delete_all` and `destroy_all`, this cop will only check cases where the receiver is a model.
|
38
|
+
# It will ignore cases where the receiver is an association (e.g., `user.articles.all.delete_all`).
|
39
|
+
# This is because omitting `all` from an association changes the methods
|
40
|
+
# from `ActiveRecord::Relation` to `ActiveRecord::Associations::CollectionProxy`,
|
41
|
+
# which can affect their behavior.
|
42
|
+
#
|
8
43
|
# @safety
|
9
44
|
# This cop is unsafe for autocorrection if the receiver for `all` is not an Active Record object.
|
10
45
|
#
|
@@ -144,13 +179,15 @@ module RuboCop
|
|
144
179
|
].to_set.freeze
|
145
180
|
|
146
181
|
POSSIBLE_ENUMERABLE_BLOCK_METHODS = %i[any? count find none? one? select sum].freeze
|
182
|
+
SENSITIVE_METHODS_ON_ASSOCIATION = %i[delete_all destroy_all].freeze
|
147
183
|
|
148
184
|
def_node_matcher :followed_by_query_method?, <<~PATTERN
|
149
185
|
(send (send _ :all) QUERYING_METHODS ...)
|
150
186
|
PATTERN
|
151
187
|
|
152
188
|
def on_send(node)
|
153
|
-
return
|
189
|
+
return unless followed_by_query_method?(node.parent)
|
190
|
+
return if possible_enumerable_block_method?(node) || sensitive_association_method?(node)
|
154
191
|
return if node.receiver ? allowed_receiver?(node.receiver) : !inherit_active_record_base?(node)
|
155
192
|
|
156
193
|
range_of_all_method = offense_range(node)
|
@@ -169,37 +206,12 @@ module RuboCop
|
|
169
206
|
parent.parent&.block_type? || parent.parent&.numblock_type? || parent.first_argument&.block_pass_type?
|
170
207
|
end
|
171
208
|
|
172
|
-
def
|
173
|
-
|
209
|
+
def sensitive_association_method?(node)
|
210
|
+
!node.receiver&.const_type? && SENSITIVE_METHODS_ON_ASSOCIATION.include?(node.parent.method_name)
|
174
211
|
end
|
175
212
|
|
176
|
-
|
177
|
-
|
178
|
-
# At that time, this duplicated module implementation can be removed.
|
179
|
-
module AllowedReceivers
|
180
|
-
def allowed_receiver?(receiver)
|
181
|
-
receiver_name = receiver_name(receiver)
|
182
|
-
|
183
|
-
allowed_receivers.include?(receiver_name)
|
184
|
-
end
|
185
|
-
|
186
|
-
def receiver_name(receiver)
|
187
|
-
return receiver_name(receiver.receiver) if receiver.receiver && !receiver.receiver.const_type?
|
188
|
-
|
189
|
-
if receiver.send_type?
|
190
|
-
if receiver.receiver
|
191
|
-
"#{receiver_name(receiver.receiver)}.#{receiver.method_name}"
|
192
|
-
else
|
193
|
-
receiver.method_name.to_s
|
194
|
-
end
|
195
|
-
else
|
196
|
-
receiver.source
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
def allowed_receivers
|
201
|
-
cop_config.fetch('AllowedReceivers', [])
|
202
|
-
end
|
213
|
+
def offense_range(node)
|
214
|
+
range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
|
203
215
|
end
|
204
216
|
end
|
205
217
|
end
|
@@ -3,25 +3,30 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
# Prefer `response.parsed_body` to `
|
6
|
+
# Prefer `response.parsed_body` to custom parsing logic for `response.body`.
|
7
7
|
#
|
8
8
|
# @safety
|
9
|
-
# This cop is unsafe because Content-Type may not be `application/json
|
10
|
-
# Content-Type provided by corporate entities such as
|
11
|
-
# `
|
9
|
+
# This cop is unsafe because Content-Type may not be `application/json` or `text/html`.
|
10
|
+
# For example, the proprietary Content-Type provided by corporate entities such as
|
11
|
+
# `application/vnd.github+json` is not supported at `response.parsed_body` by default,
|
12
|
+
# so you still have to use `JSON.parse(response.body)` there.
|
12
13
|
#
|
13
14
|
# @example
|
14
15
|
# # bad
|
15
16
|
# JSON.parse(response.body)
|
16
17
|
#
|
18
|
+
# # bad
|
19
|
+
# Nokogiri::HTML.parse(response.body)
|
20
|
+
#
|
21
|
+
# # bad
|
22
|
+
# Nokogiri::HTML5.parse(response.body)
|
23
|
+
#
|
17
24
|
# # good
|
18
25
|
# response.parsed_body
|
19
26
|
class ResponseParsedBody < Base
|
20
27
|
extend AutoCorrector
|
21
28
|
extend TargetRailsVersion
|
22
29
|
|
23
|
-
MSG = 'Prefer `response.parsed_body` to `JSON.parse(response.body)`.'
|
24
|
-
|
25
30
|
RESTRICT_ON_SEND = %i[parse].freeze
|
26
31
|
|
27
32
|
minimum_target_rails_version 5.0
|
@@ -38,12 +43,27 @@ module RuboCop
|
|
38
43
|
)
|
39
44
|
PATTERN
|
40
45
|
|
46
|
+
# @!method nokogiri_html_parse_response_body(node)
|
47
|
+
def_node_matcher :nokogiri_html_parse_response_body, <<~PATTERN
|
48
|
+
(send
|
49
|
+
(const
|
50
|
+
(const {nil? cbase} :Nokogiri)
|
51
|
+
${:HTML :HTML5}
|
52
|
+
)
|
53
|
+
:parse
|
54
|
+
(send
|
55
|
+
(send nil? :response)
|
56
|
+
:body
|
57
|
+
)
|
58
|
+
)
|
59
|
+
PATTERN
|
60
|
+
|
41
61
|
def on_send(node)
|
42
|
-
|
62
|
+
check_json_parse_response_body(node)
|
43
63
|
|
44
|
-
|
45
|
-
|
46
|
-
|
64
|
+
return unless target_rails_version >= 7.1
|
65
|
+
|
66
|
+
check_nokogiri_html_parse_response_body(node)
|
47
67
|
end
|
48
68
|
|
49
69
|
private
|
@@ -51,6 +71,28 @@ module RuboCop
|
|
51
71
|
def autocorrect(corrector, node)
|
52
72
|
corrector.replace(node, 'response.parsed_body')
|
53
73
|
end
|
74
|
+
|
75
|
+
def check_json_parse_response_body(node)
|
76
|
+
return unless json_parse_response_body?(node)
|
77
|
+
|
78
|
+
add_offense(
|
79
|
+
node,
|
80
|
+
message: 'Prefer `response.parsed_body` to `JSON.parse(response.body)`.'
|
81
|
+
) do |corrector|
|
82
|
+
autocorrect(corrector, node)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def check_nokogiri_html_parse_response_body(node)
|
87
|
+
return unless (const = nokogiri_html_parse_response_body(node))
|
88
|
+
|
89
|
+
add_offense(
|
90
|
+
node,
|
91
|
+
message: "Prefer `response.parsed_body` to `Nokogiri::#{const}.parse(response.body)`."
|
92
|
+
) do |corrector|
|
93
|
+
autocorrect(corrector, node)
|
94
|
+
end
|
95
|
+
end
|
54
96
|
end
|
55
97
|
end
|
56
98
|
end
|
@@ -17,7 +17,7 @@ module RuboCop
|
|
17
17
|
# # good
|
18
18
|
# def change
|
19
19
|
# change_table :users do |t|
|
20
|
-
# t.remove :name, :string
|
20
|
+
# t.remove :name, type: :string
|
21
21
|
# end
|
22
22
|
# end
|
23
23
|
#
|
@@ -290,10 +290,10 @@ module RuboCop
|
|
290
290
|
when :change
|
291
291
|
false
|
292
292
|
when :remove
|
293
|
-
target_rails_version >= 6.1 && all_hash_key?(node.
|
293
|
+
target_rails_version >= 6.1 && all_hash_key?(node.last_argument, :type)
|
294
294
|
when :change_default, :change_column_default, :change_table_comment,
|
295
295
|
:change_column_comment
|
296
|
-
all_hash_key?(node.
|
296
|
+
all_hash_key?(node.last_argument, :from, :to)
|
297
297
|
else
|
298
298
|
true
|
299
299
|
end
|
@@ -196,6 +196,8 @@ module RuboCop
|
|
196
196
|
end
|
197
197
|
|
198
198
|
def call_to_persisted?(node)
|
199
|
+
node = node.parent.condition if node.parenthesized_call? && node.parent.if_type?
|
200
|
+
|
199
201
|
node.send_type? && node.method?(:persisted?)
|
200
202
|
end
|
201
203
|
|
@@ -336,10 +338,10 @@ module RuboCop
|
|
336
338
|
|
337
339
|
# Check argument signature as no arguments or one hash
|
338
340
|
def expected_signature?(node)
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
341
|
+
return true unless node.arguments?
|
342
|
+
return false if !node.arguments.one? || node.method?(:destroy)
|
343
|
+
|
344
|
+
node.first_argument.hash_type? || !node.first_argument.literal?
|
343
345
|
end
|
344
346
|
end
|
345
347
|
end
|
@@ -69,9 +69,10 @@ module RuboCop
|
|
69
69
|
return if !node.receiver&.str_type? || !node.method?(:to_time)
|
70
70
|
|
71
71
|
add_offense(node.loc.selector, message: MSG_STRING_TO_TIME) do |corrector|
|
72
|
-
corrector.replace(node, "Time.zone.parse(#{node.receiver.source})")
|
72
|
+
corrector.replace(node, "Time.zone.parse(#{node.receiver.source})") unless node.csend_type?
|
73
73
|
end
|
74
74
|
end
|
75
|
+
alias on_csend on_send
|
75
76
|
|
76
77
|
private
|
77
78
|
|
@@ -68,15 +68,23 @@ module RuboCop
|
|
68
68
|
return unless uniq
|
69
69
|
|
70
70
|
add_offense(node.loc.selector) do |corrector|
|
71
|
-
|
72
|
-
|
73
|
-
corrector.remove(dot_method_with_whitespace(method, node))
|
74
|
-
corrector.insert_before(node.receiver.loc.dot.begin, '.distinct')
|
71
|
+
autocorrect(corrector, node)
|
75
72
|
end
|
76
73
|
end
|
77
74
|
|
78
75
|
private
|
79
76
|
|
77
|
+
def autocorrect(corrector, node)
|
78
|
+
method = node.method_name
|
79
|
+
|
80
|
+
corrector.remove(dot_method_with_whitespace(method, node))
|
81
|
+
if (dot = node.receiver.loc.dot)
|
82
|
+
corrector.insert_before(dot.begin, '.distinct')
|
83
|
+
else
|
84
|
+
corrector.insert_before(node.receiver, 'distinct.')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
80
88
|
def dot_method_with_whitespace(method, node)
|
81
89
|
range_between(dot_method_begin_pos(method, node), node.loc.selector.end_pos)
|
82
90
|
end
|
@@ -87,9 +87,9 @@ module RuboCop
|
|
87
87
|
|
88
88
|
def environments
|
89
89
|
@environments ||= begin
|
90
|
-
|
91
|
-
|
92
|
-
|
90
|
+
environments = cop_config['Environments'] || []
|
91
|
+
environments << 'local' if target_rails_version >= 7.1
|
92
|
+
environments
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
@@ -51,7 +51,7 @@ module RuboCop
|
|
51
51
|
uniqueness
|
52
52
|
].freeze
|
53
53
|
|
54
|
-
RESTRICT_ON_SEND = TYPES.map { |p| "validates_#{p}_of"
|
54
|
+
RESTRICT_ON_SEND = TYPES.map { |p| :"validates_#{p}_of" }.freeze
|
55
55
|
ALLOWLIST = TYPES.map { |p| "validates :column, #{p}: value" }.freeze
|
56
56
|
|
57
57
|
def on_send(node)
|
@@ -60,7 +60,7 @@ module RuboCop
|
|
60
60
|
range = node.loc.selector
|
61
61
|
|
62
62
|
add_offense(range, message: message(node)) do |corrector|
|
63
|
-
last_argument = node.
|
63
|
+
last_argument = node.last_argument
|
64
64
|
return if !last_argument.literal? && !last_argument.splat_type? && !frozen_array_argument?(last_argument)
|
65
65
|
|
66
66
|
corrector.replace(range, 'validates')
|
@@ -33,8 +33,8 @@ module RuboCop
|
|
33
33
|
|
34
34
|
def_node_matcher :where_method_call?, <<~PATTERN
|
35
35
|
{
|
36
|
-
(
|
37
|
-
(
|
36
|
+
(call _ :where (array $str_type? $_ ?))
|
37
|
+
(call _ :where $str_type? $_ ?)
|
38
38
|
}
|
39
39
|
PATTERN
|
40
40
|
|
@@ -55,6 +55,7 @@ module RuboCop
|
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
58
|
+
alias on_csend on_send
|
58
59
|
|
59
60
|
EQ_ANONYMOUS_RE = /\A([\w.]+)\s+=\s+\?\z/.freeze # column = ?
|
60
61
|
IN_ANONYMOUS_RE = /\A([\w.]+)\s+IN\s+\(\?\)\z/i.freeze # column IN (?)
|
@@ -55,11 +55,11 @@ module RuboCop
|
|
55
55
|
RESTRICT_ON_SEND = %i[exists?].freeze
|
56
56
|
|
57
57
|
def_node_matcher :where_exists_call?, <<~PATTERN
|
58
|
-
(
|
58
|
+
(call (call _ :where $...) :exists?)
|
59
59
|
PATTERN
|
60
60
|
|
61
61
|
def_node_matcher :exists_with_args?, <<~PATTERN
|
62
|
-
(
|
62
|
+
(call _ :exists? $...)
|
63
63
|
PATTERN
|
64
64
|
|
65
65
|
def on_send(node)
|
@@ -67,7 +67,7 @@ module RuboCop
|
|
67
67
|
return unless convertable_args?(args)
|
68
68
|
|
69
69
|
range = correction_range(node)
|
70
|
-
good_method = build_good_method(args)
|
70
|
+
good_method = build_good_method(args, dot: node.loc.dot)
|
71
71
|
message = format(MSG, good_method: good_method, bad_method: range.source)
|
72
72
|
|
73
73
|
add_offense(range, message: message) do |corrector|
|
@@ -75,6 +75,7 @@ module RuboCop
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
78
|
+
alias on_csend on_send
|
78
79
|
|
79
80
|
private
|
80
81
|
|
@@ -108,11 +109,11 @@ module RuboCop
|
|
108
109
|
end
|
109
110
|
end
|
110
111
|
|
111
|
-
def build_good_method(args)
|
112
|
+
def build_good_method(args, dot:)
|
112
113
|
if exists_style?
|
113
114
|
build_good_method_exists(args)
|
114
115
|
elsif where_style?
|
115
|
-
build_good_method_where(args)
|
116
|
+
build_good_method_where(args, dot&.source || '.')
|
116
117
|
end
|
117
118
|
end
|
118
119
|
|
@@ -124,11 +125,11 @@ module RuboCop
|
|
124
125
|
end
|
125
126
|
end
|
126
127
|
|
127
|
-
def build_good_method_where(args)
|
128
|
+
def build_good_method_where(args, dot_source)
|
128
129
|
if args.size > 1
|
129
|
-
"where(#{args.map(&:source).join(', ')})
|
130
|
+
"where(#{args.map(&:source).join(', ')})#{dot_source}exists?"
|
130
131
|
else
|
131
|
-
"where(#{args[0].source})
|
132
|
+
"where(#{args[0].source})#{dot_source}exists?"
|
132
133
|
end
|
133
134
|
end
|
134
135
|
end
|
@@ -36,7 +36,7 @@ module RuboCop
|
|
36
36
|
PATTERN
|
37
37
|
|
38
38
|
def on_send(node)
|
39
|
-
return unless node.first_argument
|
39
|
+
return unless node.first_argument&.sym_type?
|
40
40
|
|
41
41
|
root_receiver = root_receiver(node)
|
42
42
|
where_node_and_argument(root_receiver) do |where_node, where_argument|
|
@@ -89,16 +89,20 @@ module RuboCop
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
+
# rubocop:disable Metrics/AbcSize
|
92
93
|
def remove_where_method(corrector, node, where_node)
|
93
94
|
range = range_between(where_node.loc.selector.begin_pos, where_node.loc.end.end_pos)
|
94
95
|
if node.multiline? && !same_line?(node, where_node)
|
95
96
|
range = range_by_whole_lines(range, include_final_newline: true)
|
96
|
-
|
97
|
+
elsif where_node.receiver
|
97
98
|
corrector.remove(where_node.loc.dot)
|
99
|
+
else
|
100
|
+
corrector.remove(node.loc.dot)
|
98
101
|
end
|
99
102
|
|
100
103
|
corrector.remove(range)
|
101
104
|
end
|
105
|
+
# rubocop:enable Metrics/AbcSize
|
102
106
|
|
103
107
|
def same_line?(left_joins_node, where_node)
|
104
108
|
left_joins_node.loc.selector.line == where_node.loc.selector.line
|
@@ -32,8 +32,8 @@ module RuboCop
|
|
32
32
|
|
33
33
|
def_node_matcher :where_method_call?, <<~PATTERN
|
34
34
|
{
|
35
|
-
(
|
36
|
-
(
|
35
|
+
(call _ :where (array $str_type? $_ ?))
|
36
|
+
(call _ :where $str_type? $_ ?)
|
37
37
|
}
|
38
38
|
PATTERN
|
39
39
|
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
46
46
|
column_and_value = extract_column_and_value(template_node, value_node)
|
47
47
|
return unless column_and_value
|
48
48
|
|
49
|
-
good_method = build_good_method(*column_and_value)
|
49
|
+
good_method = build_good_method(node.loc.dot&.source, *column_and_value)
|
50
50
|
message = format(MSG, good_method: good_method)
|
51
51
|
|
52
52
|
add_offense(range, message: message) do |corrector|
|
@@ -54,6 +54,7 @@ module RuboCop
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
57
|
+
alias on_csend on_send
|
57
58
|
|
58
59
|
NOT_EQ_ANONYMOUS_RE = /\A([\w.]+)\s+(?:!=|<>)\s+\?\z/.freeze # column != ?, column <> ?
|
59
60
|
NOT_IN_ANONYMOUS_RE = /\A([\w.]+)\s+NOT\s+IN\s+\(\?\)\z/i.freeze # column NOT IN (?)
|
@@ -86,13 +87,14 @@ module RuboCop
|
|
86
87
|
[Regexp.last_match(1), value]
|
87
88
|
end
|
88
89
|
|
89
|
-
def build_good_method(column, value)
|
90
|
+
def build_good_method(dot, column, value)
|
91
|
+
dot ||= '.'
|
90
92
|
if column.include?('.')
|
91
93
|
table, column = column.split('.')
|
92
94
|
|
93
|
-
"where
|
95
|
+
"where#{dot}not(#{table}: { #{column}: #{value} })"
|
94
96
|
else
|
95
|
-
"where
|
97
|
+
"where#{dot}not(#{column}: #{value})"
|
96
98
|
end
|
97
99
|
end
|
98
100
|
end
|
@@ -30,6 +30,7 @@ module RuboCop
|
|
30
30
|
|
31
31
|
def build!(ast)
|
32
32
|
raise "Unexpected type: #{ast.type}" unless ast.block_type?
|
33
|
+
return unless ast.body
|
33
34
|
|
34
35
|
each_table(ast) do |table_def|
|
35
36
|
next unless table_def.method?(:create_table)
|
@@ -127,7 +128,7 @@ module RuboCop
|
|
127
128
|
private
|
128
129
|
|
129
130
|
def analyze_keywords!(node)
|
130
|
-
pairs = node.
|
131
|
+
pairs = node.last_argument
|
131
132
|
return unless pairs.hash_type?
|
132
133
|
|
133
134
|
pairs.each_pair do |k, v|
|
@@ -158,7 +159,7 @@ module RuboCop
|
|
158
159
|
end
|
159
160
|
|
160
161
|
def analyze_keywords!(node)
|
161
|
-
pairs = node.
|
162
|
+
pairs = node.last_argument
|
162
163
|
return unless pairs.hash_type?
|
163
164
|
|
164
165
|
pairs.each_pair do |k, v|
|
@@ -12,10 +12,10 @@ module RuboCop
|
|
12
12
|
# So a cop that uses the loader should handle `nil` properly.
|
13
13
|
#
|
14
14
|
# @return [Schema, nil]
|
15
|
-
def load(target_ruby_version)
|
15
|
+
def load(target_ruby_version, parser_engine)
|
16
16
|
return @load if defined?(@load)
|
17
17
|
|
18
|
-
@load = load!(target_ruby_version)
|
18
|
+
@load = load!(target_ruby_version, parser_engine)
|
19
19
|
end
|
20
20
|
|
21
21
|
def reset!
|
@@ -38,23 +38,13 @@ module RuboCop
|
|
38
38
|
|
39
39
|
private
|
40
40
|
|
41
|
-
def load!(target_ruby_version)
|
41
|
+
def load!(target_ruby_version, parser_engine)
|
42
42
|
path = db_schema_path
|
43
43
|
return unless path
|
44
44
|
|
45
|
-
ast =
|
46
|
-
Schema.new(ast) if ast
|
47
|
-
end
|
48
|
-
|
49
|
-
def parse(path, target_ruby_version)
|
50
|
-
klass_name = :"Ruby#{target_ruby_version.to_s.sub('.', '')}"
|
51
|
-
klass = ::Parser.const_get(klass_name)
|
52
|
-
parser = klass.new(RuboCop::AST::Builder.new)
|
45
|
+
ast = RuboCop::ProcessedSource.new(File.read(path), target_ruby_version, path, parser_engine: parser_engine).ast
|
53
46
|
|
54
|
-
|
55
|
-
buffer.source = path.read
|
56
|
-
|
57
|
-
parser.parse(buffer)
|
47
|
+
Schema.new(ast) if ast
|
58
48
|
end
|
59
49
|
end
|
60
50
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.24.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2024-03-25 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -60,6 +60,26 @@ dependencies:
|
|
60
60
|
- - "<"
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '2.0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rubocop-ast
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.31.1
|
70
|
+
- - "<"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '2.0'
|
73
|
+
type: :runtime
|
74
|
+
prerelease: false
|
75
|
+
version_requirements: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 1.31.1
|
80
|
+
- - "<"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.0'
|
63
83
|
description: |
|
64
84
|
Automatic Rails code style checking tool.
|
65
85
|
A RuboCop extension focused on enforcing Rails best practices and coding conventions.
|
@@ -225,7 +245,7 @@ metadata:
|
|
225
245
|
homepage_uri: https://docs.rubocop.org/rubocop-rails/
|
226
246
|
changelog_uri: https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md
|
227
247
|
source_code_uri: https://github.com/rubocop/rubocop-rails/
|
228
|
-
documentation_uri: https://docs.rubocop.org/rubocop-rails/2.
|
248
|
+
documentation_uri: https://docs.rubocop.org/rubocop-rails/2.24/
|
229
249
|
bug_tracker_uri: https://github.com/rubocop/rubocop-rails/issues
|
230
250
|
rubygems_mfa_required: 'true'
|
231
251
|
post_install_message:
|
@@ -243,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
263
|
- !ruby/object:Gem::Version
|
244
264
|
version: '0'
|
245
265
|
requirements: []
|
246
|
-
rubygems_version: 3.
|
266
|
+
rubygems_version: 3.3.26
|
247
267
|
signing_key:
|
248
268
|
specification_version: 4
|
249
269
|
summary: Automatic Rails code style checking tool.
|