rubocop-rails 2.25.1 → 2.32.0
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 +60 -8
- data/config/default.yml +103 -51
- data/lib/rubocop/cop/mixin/active_record_helper.rb +2 -2
- data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +2 -2
- data/lib/rubocop/cop/mixin/database_type_resolvable.rb +2 -2
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +6 -1
- data/lib/rubocop/cop/mixin/index_method.rb +69 -61
- data/lib/rubocop/cop/mixin/routes_helper.rb +20 -0
- data/lib/rubocop/cop/mixin/target_rails_version.rb +3 -5
- data/lib/rubocop/cop/rails/action_order.rb +1 -5
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +1 -5
- data/lib/rubocop/cop/rails/add_column_index.rb +1 -0
- data/lib/rubocop/cop/rails/application_record.rb +4 -0
- data/lib/rubocop/cop/rails/arel_star.rb +5 -5
- 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 +3 -2
- data/lib/rubocop/cop/rails/compact_blank.rb +29 -8
- data/lib/rubocop/cop/rails/content_tag.rb +1 -1
- data/lib/rubocop/cop/rails/dangerous_column_names.rb +2 -0
- data/lib/rubocop/cop/rails/date.rb +2 -2
- data/lib/rubocop/cop/rails/delegate.rb +53 -7
- data/lib/rubocop/cop/rails/duplicate_association.rb +8 -4
- data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +1 -3
- 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 +26 -3
- data/lib/rubocop/cop/rails/file_path.rb +62 -10
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +7 -0
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +1 -1
- data/lib/rubocop/cop/rails/index_by.rb +37 -12
- data/lib/rubocop/cop/rails/index_with.rb +37 -12
- data/lib/rubocop/cop/rails/inquiry.rb +1 -1
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +11 -1
- 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 +6 -2
- data/lib/rubocop/cop/rails/output.rb +1 -2
- data/lib/rubocop/cop/rails/pluck.rb +30 -4
- data/lib/rubocop/cop/rails/pluck_in_where.rb +17 -8
- 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/redundant_active_record_all_method.rb +1 -30
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +1 -1
- data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +9 -0
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +7 -2
- data/lib/rubocop/cop/rails/reflection_class_name.rb +3 -3
- 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/reversible_migration.rb +4 -1
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +21 -12
- data/lib/rubocop/cop/rails/save_bang.rb +8 -7
- data/lib/rubocop/cop/rails/schema_comment.rb +2 -1
- data/lib/rubocop/cop/rails/select_map.rb +3 -2
- data/lib/rubocop/cop/rails/skips_model_validations.rb +5 -3
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +1 -1
- 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 +3 -2
- data/lib/rubocop/cop/rails/time_zone.rb +16 -7
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +7 -2
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +10 -33
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +1 -1
- data/lib/rubocop/cop/rails/validation.rb +1 -1
- data/lib/rubocop/cop/rails/where_equals.rb +28 -12
- data/lib/rubocop/cop/rails/where_not.rb +11 -6
- data/lib/rubocop/cop/rails/where_range.rb +7 -2
- data/lib/rubocop/cop/rails_cops.rb +4 -0
- data/lib/rubocop/rails/migration_file_skippable.rb +54 -0
- data/lib/rubocop/rails/plugin.rb +48 -0
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop/rails.rb +1 -8
- data/lib/rubocop-rails.rb +4 -5
- metadata +29 -12
- data/lib/rubocop/rails/inject.rb +0 -18
@@ -41,10 +41,14 @@ module RuboCop
|
|
41
41
|
# change_column_null :products, :category_id, false
|
42
42
|
class NotNullColumn < Base
|
43
43
|
include DatabaseTypeResolvable
|
44
|
+
include MigrationsHelper
|
44
45
|
|
45
46
|
MSG = 'Do not add a NOT NULL column without a default value.'
|
46
47
|
RESTRICT_ON_SEND = %i[add_column add_reference].freeze
|
47
48
|
|
49
|
+
VIRTUAL_TYPE_VALUES = [:virtual, 'virtual'].freeze
|
50
|
+
TEXT_TYPE_VALUES = [:text, 'text'].freeze
|
51
|
+
|
48
52
|
def_node_matcher :add_not_null_column?, <<~PATTERN
|
49
53
|
(send nil? :add_column _ _ $_ (hash $...))
|
50
54
|
PATTERN
|
@@ -91,8 +95,8 @@ module RuboCop
|
|
91
95
|
|
92
96
|
def check_column(type, pairs)
|
93
97
|
if type.respond_to?(:value)
|
94
|
-
return if
|
95
|
-
return if (type.value
|
98
|
+
return if VIRTUAL_TYPE_VALUES.include?(type.value)
|
99
|
+
return if TEXT_TYPE_VALUES.include?(type.value) && database == MYSQL
|
96
100
|
end
|
97
101
|
|
98
102
|
check_pairs(pairs)
|
@@ -23,7 +23,6 @@ module RuboCop
|
|
23
23
|
|
24
24
|
MSG = "Do not write to stdout. Use Rails's logger if you want to log."
|
25
25
|
RESTRICT_ON_SEND = %i[ap p pp pretty_print print puts binwrite syswrite write write_nonblock].freeze
|
26
|
-
ALLOWED_TYPES = %i[send csend block numblock].freeze
|
27
26
|
|
28
27
|
def_node_matcher :output?, <<~PATTERN
|
29
28
|
(send nil? {:ap :p :pp :pretty_print :print :puts} ...)
|
@@ -40,7 +39,7 @@ module RuboCop
|
|
40
39
|
PATTERN
|
41
40
|
|
42
41
|
def on_send(node)
|
43
|
-
return if
|
42
|
+
return if node.parent&.call_type? || node.block_node
|
44
43
|
return if !output?(node) && !io_output?(node)
|
45
44
|
|
46
45
|
range = offense_range(node)
|
@@ -9,6 +9,24 @@ module RuboCop
|
|
9
9
|
# element in an enumerable. When called on an Active Record relation, it
|
10
10
|
# results in a more efficient query that only selects the necessary key.
|
11
11
|
#
|
12
|
+
# NOTE: If the receiver's relation is not loaded and `pluck` is used inside an iteration,
|
13
|
+
# it may result in N+1 queries because `pluck` queries the database on each iteration.
|
14
|
+
# This cop ignores offenses for `map/collect` when they are suspected to be part of an iteration
|
15
|
+
# to prevent such potential issues.
|
16
|
+
#
|
17
|
+
# [source,ruby]
|
18
|
+
# ----
|
19
|
+
# users = User.all
|
20
|
+
# 5.times do
|
21
|
+
# users.map { |user| user[:foo] } # Only one query is executed
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# users = User.all
|
25
|
+
# 5.times do
|
26
|
+
# users.pluck(:id) # A query is executed on every iteration
|
27
|
+
# end
|
28
|
+
# ----
|
29
|
+
#
|
12
30
|
# @safety
|
13
31
|
# This cop is unsafe because model can use column aliases.
|
14
32
|
#
|
@@ -38,30 +56,38 @@ module RuboCop
|
|
38
56
|
minimum_target_rails_version 5.0
|
39
57
|
|
40
58
|
def_node_matcher :pluck_candidate?, <<~PATTERN
|
41
|
-
(
|
59
|
+
(any_block (call _ {:map :collect}) $_argument (send lvar :[] $_key))
|
42
60
|
PATTERN
|
43
61
|
|
62
|
+
# rubocop:disable Metrics/AbcSize
|
44
63
|
def on_block(node)
|
64
|
+
return if node.each_ancestor(:any_block).any?
|
65
|
+
|
45
66
|
pluck_candidate?(node) do |argument, key|
|
46
67
|
next if key.regexp_type? || !use_one_block_argument?(argument)
|
47
68
|
|
48
69
|
match = if node.block_type?
|
49
70
|
block_argument = argument.children.first.source
|
50
71
|
use_block_argument_in_key?(block_argument, key)
|
51
|
-
|
52
|
-
|
72
|
+
elsif node.numblock_type?
|
73
|
+
use_block_argument_in_key?('_1', key)
|
74
|
+
else # itblock
|
75
|
+
use_block_argument_in_key?('it', key)
|
53
76
|
end
|
54
77
|
next unless match
|
55
78
|
|
56
79
|
register_offense(node, key)
|
57
80
|
end
|
58
81
|
end
|
82
|
+
# rubocop:enable Metrics/AbcSize
|
59
83
|
alias on_numblock on_block
|
84
|
+
alias on_itblock on_block
|
60
85
|
|
61
86
|
private
|
62
87
|
|
63
88
|
def use_one_block_argument?(argument)
|
64
|
-
|
89
|
+
# Checks for numbered argument `_1` or `it block parameter.
|
90
|
+
return true if [1, :it].include?(argument)
|
65
91
|
|
66
92
|
argument.respond_to?(:one?) && argument.one?
|
67
93
|
end
|
@@ -7,17 +7,26 @@ module RuboCop
|
|
7
7
|
# and can be replaced with `select`.
|
8
8
|
#
|
9
9
|
# Since `pluck` is an eager method and hits the database immediately,
|
10
|
-
# using `select` helps to avoid additional database queries
|
10
|
+
# using `select` helps to avoid additional database queries by running as
|
11
|
+
# a subquery.
|
11
12
|
#
|
12
|
-
# This cop has two
|
13
|
-
#
|
14
|
-
# (
|
13
|
+
# This cop has two modes of enforcement. When the `EnforcedStyle` is set
|
14
|
+
# to `conservative` (the default), only calls to `pluck` on a constant
|
15
|
+
# (e.g. a model class) within `where` are considered offenses.
|
15
16
|
#
|
16
17
|
# @safety
|
17
|
-
# When
|
18
|
-
# `where`
|
19
|
-
#
|
20
|
-
# `ActiveRecord::Relation` instance
|
18
|
+
# When `EnforcedStyle` is set to `aggressive`, all calls to `pluck`
|
19
|
+
# within `where` are considered offenses. This might lead to false
|
20
|
+
# positives because the check cannot distinguish between calls to
|
21
|
+
# `pluck` on an `ActiveRecord::Relation` instance and calls to `pluck`
|
22
|
+
# on an `Array` instance.
|
23
|
+
#
|
24
|
+
# Additionally, when using a subquery with the SQL `IN` operator,
|
25
|
+
# databases like PostgreSQL and MySQL can't optimize complex queries as
|
26
|
+
# well. They need to scan all records of the outer table against the
|
27
|
+
# subquery result sequentially, rather than using an index. This can
|
28
|
+
# cause significant performance issues compared to writing the query
|
29
|
+
# differently or using `pluck`.
|
21
30
|
#
|
22
31
|
# @example
|
23
32
|
# # bad
|
@@ -10,25 +10,39 @@ module RuboCop
|
|
10
10
|
# # bad
|
11
11
|
# 3.day.ago
|
12
12
|
# 1.months.ago
|
13
|
+
# 5.megabyte
|
14
|
+
# 1.gigabytes
|
13
15
|
#
|
14
16
|
# # good
|
15
17
|
# 3.days.ago
|
16
18
|
# 1.month.ago
|
19
|
+
# 5.megabytes
|
20
|
+
# 1.gigabyte
|
17
21
|
class PluralizationGrammar < Base
|
18
22
|
extend AutoCorrector
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
SINGULAR_METHODS = {
|
25
|
+
second: :seconds,
|
26
|
+
minute: :minutes,
|
27
|
+
hour: :hours,
|
28
|
+
day: :days,
|
29
|
+
week: :weeks,
|
30
|
+
fortnight: :fortnights,
|
31
|
+
month: :months,
|
32
|
+
year: :years,
|
33
|
+
byte: :bytes,
|
34
|
+
kilobyte: :kilobytes,
|
35
|
+
megabyte: :megabytes,
|
36
|
+
gigabyte: :gigabytes,
|
37
|
+
terabyte: :terabytes,
|
38
|
+
petabyte: :petabytes,
|
39
|
+
exabyte: :exabytes,
|
40
|
+
zettabyte: :zettabytes
|
41
|
+
}.freeze
|
42
|
+
|
43
|
+
RESTRICT_ON_SEND = SINGULAR_METHODS.keys + SINGULAR_METHODS.values
|
44
|
+
|
45
|
+
PLURAL_METHODS = SINGULAR_METHODS.invert.freeze
|
32
46
|
|
33
47
|
MSG = 'Prefer `%<number>s.%<correct>s`.'
|
34
48
|
|
@@ -82,19 +96,19 @@ module RuboCop
|
|
82
96
|
end
|
83
97
|
|
84
98
|
def literal_number?(node)
|
85
|
-
node
|
99
|
+
node&.type?(:int, :float)
|
86
100
|
end
|
87
101
|
|
88
102
|
def pluralize(method_name)
|
89
|
-
|
103
|
+
SINGULAR_METHODS.fetch(method_name.to_sym).to_s
|
90
104
|
end
|
91
105
|
|
92
106
|
def singularize(method_name)
|
93
|
-
|
107
|
+
PLURAL_METHODS.fetch(method_name.to_sym).to_s
|
94
108
|
end
|
95
109
|
|
96
110
|
def duration_method?(method_name)
|
97
|
-
|
111
|
+
SINGULAR_METHODS.key?(method_name) || PLURAL_METHODS.key?(method_name)
|
98
112
|
end
|
99
113
|
end
|
100
114
|
end
|
@@ -98,8 +98,6 @@ module RuboCop
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def on_or(node)
|
101
|
-
return unless cop_config['NilOrEmpty']
|
102
|
-
|
103
101
|
exists_and_not_empty?(node) do |var1, var2|
|
104
102
|
return unless var1 == var2
|
105
103
|
|
@@ -112,7 +110,7 @@ module RuboCop
|
|
112
110
|
def on_if(node)
|
113
111
|
return unless cop_config['UnlessBlank']
|
114
112
|
return unless node.unless?
|
115
|
-
return if node.else? && config.
|
113
|
+
return if node.else? && config.cop_enabled?('Style/UnlessElse')
|
116
114
|
|
117
115
|
unless_blank?(node) do |method_call, receiver|
|
118
116
|
range = unless_condition(node, method_call)
|
@@ -3,35 +3,6 @@
|
|
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
|
-
|
35
6
|
# Detect redundant `all` used as a receiver for Active Record query methods.
|
36
7
|
#
|
37
8
|
# For the methods `delete_all` and `destroy_all`, this cop will only check cases where the receiver is a model.
|
@@ -203,7 +174,7 @@ module RuboCop
|
|
203
174
|
parent = node.parent
|
204
175
|
return false unless POSSIBLE_ENUMERABLE_BLOCK_METHODS.include?(parent.method_name)
|
205
176
|
|
206
|
-
parent.
|
177
|
+
parent.block_literal? || parent.first_argument&.block_pass_type?
|
207
178
|
end
|
208
179
|
|
209
180
|
def sensitive_association_method?(node)
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
40
40
|
def on_send(node)
|
41
41
|
association_with_foreign_key(node) do |type, name, options, foreign_key_pair, foreign_key|
|
42
42
|
if redundant?(node, type, name, options, foreign_key)
|
43
|
-
add_offense(foreign_key_pair
|
43
|
+
add_offense(foreign_key_pair) do |corrector|
|
44
44
|
range = range_with_surrounding_space(foreign_key_pair.source_range, side: :left)
|
45
45
|
range = range_with_surrounding_comma(range, :left)
|
46
46
|
|
@@ -39,6 +39,9 @@ module RuboCop
|
|
39
39
|
MSG = 'Remove explicit presence validation for %<association>s.'
|
40
40
|
RESTRICT_ON_SEND = %i[validates].freeze
|
41
41
|
|
42
|
+
# From https://github.com/rails/rails/blob/7a0bf93b9dd291c7f61121a41b3a813ac8857e6a/activemodel/lib/active_model/validations/validates.rb#L157-L159
|
43
|
+
NON_VALIDATION_OPTIONS = %i[if unless on allow_blank allow_nil strict].freeze
|
44
|
+
|
42
45
|
minimum_target_rails_version 5.0
|
43
46
|
|
44
47
|
# @!method presence_validation?(node)
|
@@ -170,6 +173,12 @@ module RuboCop
|
|
170
173
|
|
171
174
|
def on_send(node)
|
172
175
|
presence_validation?(node) do |all_keys, options, presence|
|
176
|
+
# If presence is the only validation option and other non-validation options
|
177
|
+
# are present, removing it will cause rails to error.
|
178
|
+
used_option_keys = options.keys.select(&:sym_type?).map(&:value)
|
179
|
+
remaining_validations = used_option_keys - NON_VALIDATION_OPTIONS - [:presence]
|
180
|
+
return if remaining_validations.none? && options.keys.length > 1
|
181
|
+
|
173
182
|
keys = non_optional_belongs_to(node.parent, all_keys)
|
174
183
|
return if keys.none?
|
175
184
|
|
@@ -78,25 +78,29 @@ module RuboCop
|
|
78
78
|
|
79
79
|
send_nodes.each do |send_node|
|
80
80
|
receiver = send_node.receiver
|
81
|
-
add_offense(receiver
|
81
|
+
add_offense(receiver) do |corrector|
|
82
82
|
autocorrect(corrector, send_node, node)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
87
|
alias on_numblock on_block
|
88
|
+
alias on_itblock on_block
|
88
89
|
|
89
90
|
private
|
90
91
|
|
91
92
|
def autocorrect(corrector, send_node, node)
|
92
93
|
corrector.remove(send_node.receiver)
|
93
94
|
corrector.remove(send_node.loc.dot)
|
94
|
-
corrector.remove(block_argument_range(send_node))
|
95
|
+
corrector.remove(block_argument_range(send_node)) if node.block_type?
|
95
96
|
end
|
96
97
|
|
98
|
+
# rubocop:disable Metrics/AbcSize
|
97
99
|
def redundant_receiver?(send_nodes, node)
|
98
100
|
proc = if node.numblock_type?
|
99
101
|
->(n) { n.receiver.lvar_type? && n.receiver.source == '_1' }
|
102
|
+
elsif node.itblock_type?
|
103
|
+
->(n) { n.receiver.lvar_type? && n.receiver.source == 'it' }
|
100
104
|
else
|
101
105
|
return false if node.arguments.empty?
|
102
106
|
|
@@ -106,6 +110,7 @@ module RuboCop
|
|
106
110
|
|
107
111
|
send_nodes.all?(&proc)
|
108
112
|
end
|
113
|
+
# rubocop:enable Metrics/AbcSize
|
109
114
|
|
110
115
|
def block_argument_range(node)
|
111
116
|
block_node = node.each_ancestor(:block).first
|
@@ -40,10 +40,10 @@ module RuboCop
|
|
40
40
|
|
41
41
|
def on_send(node)
|
42
42
|
association_with_reflection(node) do |reflection_class_name|
|
43
|
-
return if reflection_class_name.value.send_type? && reflection_class_name.value.receiver
|
43
|
+
return if reflection_class_name.value.send_type? && !reflection_class_name.value.receiver&.const_type?
|
44
44
|
return if reflection_class_name.value.lvar_type? && str_assigned?(reflection_class_name)
|
45
45
|
|
46
|
-
add_offense(reflection_class_name
|
46
|
+
add_offense(reflection_class_name) do |corrector|
|
47
47
|
autocorrect(corrector, reflection_class_name)
|
48
48
|
end
|
49
49
|
end
|
@@ -76,7 +76,7 @@ module RuboCop
|
|
76
76
|
def autocorrect(corrector, class_config)
|
77
77
|
class_value = class_config.value
|
78
78
|
replacement = const_or_string(class_value)
|
79
|
-
return unless replacement
|
79
|
+
return unless replacement
|
80
80
|
|
81
81
|
corrector.replace(class_value, replacement.source.inspect)
|
82
82
|
end
|
@@ -53,9 +53,12 @@ module RuboCop
|
|
53
53
|
node.pairs.find { |p| p.key.value.to_sym == :content_type }
|
54
54
|
end
|
55
55
|
|
56
|
-
def compatible_content_type?(
|
57
|
-
|
58
|
-
|
56
|
+
def compatible_content_type?(pair_node)
|
57
|
+
if pair_node.nil?
|
58
|
+
!cop_config['ContentTypeCompatibility']
|
59
|
+
elsif pair_node.value.respond_to?(:value)
|
60
|
+
pair_node.value.value == 'text/plain'
|
61
|
+
end
|
59
62
|
end
|
60
63
|
|
61
64
|
def replacement(rest_options, option_value)
|
@@ -205,6 +205,7 @@ module RuboCop
|
|
205
205
|
end
|
206
206
|
|
207
207
|
alias on_numblock on_block
|
208
|
+
alias on_itblock on_block
|
208
209
|
|
209
210
|
private
|
210
211
|
|
@@ -215,8 +216,10 @@ module RuboCop
|
|
215
216
|
end
|
216
217
|
|
217
218
|
def check_drop_table_node(node)
|
219
|
+
return unless (last_argument = node.last_argument)
|
220
|
+
|
218
221
|
drop_table_call(node) do
|
219
|
-
unless node.parent.
|
222
|
+
unless node.parent.any_block_type? || last_argument.block_pass_type?
|
220
223
|
add_offense(node, message: format(MSG, action: 'drop_table(without block)'))
|
221
224
|
end
|
222
225
|
end
|
@@ -23,6 +23,8 @@ module RuboCop
|
|
23
23
|
# File.binread(Rails.root.join('db', 'schema.rb'))
|
24
24
|
# File.write(Rails.root.join('db', 'schema.rb'), content)
|
25
25
|
# File.binwrite(Rails.root.join('db', 'schema.rb'), content)
|
26
|
+
# Dir.glob(Rails.root.join('db', 'schema.rb'))
|
27
|
+
# Dir[Rails.root.join('db', 'schema.rb')]
|
26
28
|
#
|
27
29
|
# # good
|
28
30
|
# Rails.root.join('db', 'schema.rb').open
|
@@ -31,14 +33,15 @@ module RuboCop
|
|
31
33
|
# Rails.root.join('db', 'schema.rb').binread
|
32
34
|
# Rails.root.join('db', 'schema.rb').write(content)
|
33
35
|
# Rails.root.join('db', 'schema.rb').binwrite(content)
|
36
|
+
# Rails.root.glob("db/schema.rb")
|
34
37
|
#
|
35
38
|
class RootPathnameMethods < Base # rubocop:disable Metrics/ClassLength
|
36
39
|
extend AutoCorrector
|
37
40
|
include RangeHelp
|
38
41
|
|
39
|
-
MSG = '`%<rails_root>s` is a `Pathname
|
42
|
+
MSG = '`%<rails_root>s` is a `Pathname`, so you can use `%<replacement>s`.'
|
40
43
|
|
41
|
-
DIR_GLOB_METHODS = %i[glob].to_set.freeze
|
44
|
+
DIR_GLOB_METHODS = %i[[] glob].to_set.freeze
|
42
45
|
|
43
46
|
DIR_NON_GLOB_METHODS = %i[
|
44
47
|
children
|
@@ -171,7 +174,7 @@ module RuboCop
|
|
171
174
|
|
172
175
|
def_node_matcher :dir_glob?, <<~PATTERN
|
173
176
|
(send
|
174
|
-
(const {cbase nil?} :Dir)
|
177
|
+
(const {cbase nil?} :Dir) DIR_GLOB_METHODS ...)
|
175
178
|
PATTERN
|
176
179
|
|
177
180
|
def_node_matcher :rails_root_pathname?, <<~PATTERN
|
@@ -188,13 +191,14 @@ module RuboCop
|
|
188
191
|
|
189
192
|
def on_send(node)
|
190
193
|
evidence(node) do |method, path, args, rails_root|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
end
|
194
|
+
replacement = if dir_glob?(node)
|
195
|
+
build_path_glob_replacement(path)
|
196
|
+
else
|
197
|
+
build_path_replacement(path, method, args)
|
198
|
+
end
|
197
199
|
|
200
|
+
message = format(MSG, rails_root: rails_root.source, replacement: replacement)
|
201
|
+
add_offense(node, message: message) do |corrector|
|
198
202
|
corrector.replace(node, replacement)
|
199
203
|
end
|
200
204
|
end
|
@@ -217,12 +221,12 @@ module RuboCop
|
|
217
221
|
end
|
218
222
|
end
|
219
223
|
|
220
|
-
def build_path_glob_replacement(path
|
224
|
+
def build_path_glob_replacement(path)
|
221
225
|
receiver = range_between(path.source_range.begin_pos, path.children.first.loc.selector.end_pos).source
|
222
226
|
|
223
227
|
argument = path.arguments.one? ? path.first_argument.source : join_arguments(path.arguments)
|
224
228
|
|
225
|
-
"#{receiver}
|
229
|
+
"#{receiver}.glob(#{argument})"
|
226
230
|
end
|
227
231
|
|
228
232
|
def build_path_replacement(path, method, args)
|
@@ -233,7 +237,12 @@ module RuboCop
|
|
233
237
|
end
|
234
238
|
|
235
239
|
replacement = "#{path_replacement}.#{method}"
|
236
|
-
|
240
|
+
|
241
|
+
if args.any?
|
242
|
+
formatted_args = args.map { |arg| arg.array_type? ? "*#{arg.source}" : arg.source }
|
243
|
+
replacement += "(#{formatted_args.join(', ')})"
|
244
|
+
end
|
245
|
+
|
237
246
|
replacement
|
238
247
|
end
|
239
248
|
|
@@ -182,7 +182,7 @@ module RuboCop
|
|
182
182
|
def right_assignment_node(assignment)
|
183
183
|
node = assignment.node.child_nodes.first
|
184
184
|
|
185
|
-
return node unless node&.
|
185
|
+
return node unless node&.any_block_type?
|
186
186
|
|
187
187
|
node.send_node
|
188
188
|
end
|
@@ -244,11 +244,11 @@ module RuboCop
|
|
244
244
|
end
|
245
245
|
|
246
246
|
def operator_or_single_negative?(node)
|
247
|
-
node.
|
247
|
+
node.operator_keyword? || single_negative?(node)
|
248
248
|
end
|
249
249
|
|
250
250
|
def conditional?(parent)
|
251
|
-
parent.
|
251
|
+
parent.type?(:if, :case)
|
252
252
|
end
|
253
253
|
|
254
254
|
def deparenthesize(node)
|
@@ -305,7 +305,7 @@ module RuboCop
|
|
305
305
|
|
306
306
|
node = assignable_node(node)
|
307
307
|
method, sibling_index = find_method_with_sibling_index(node.parent)
|
308
|
-
return false unless method
|
308
|
+
return false unless method&.type?(:def, :any_block)
|
309
309
|
|
310
310
|
method.children.size == node.sibling_index + sibling_index
|
311
311
|
end
|
@@ -324,12 +324,13 @@ module RuboCop
|
|
324
324
|
|
325
325
|
def explicit_return?(node)
|
326
326
|
ret = assignable_node(node).parent
|
327
|
-
ret
|
327
|
+
ret&.type?(:return, :next)
|
328
328
|
end
|
329
329
|
|
330
330
|
def return_value_assigned?(node)
|
331
|
-
assignment = assignable_node(node).parent
|
332
|
-
|
331
|
+
return false unless (assignment = assignable_node(node).parent)
|
332
|
+
|
333
|
+
assignment.assignment?
|
333
334
|
end
|
334
335
|
|
335
336
|
def persist_method?(node, methods = RESTRICT_ON_SEND)
|
@@ -23,6 +23,7 @@ module RuboCop
|
|
23
23
|
#
|
24
24
|
class SchemaComment < Base
|
25
25
|
include ActiveRecordMigrationsHelper
|
26
|
+
include MigrationsHelper
|
26
27
|
|
27
28
|
COLUMN_MSG = 'New database column without `comment`.'
|
28
29
|
TABLE_MSG = 'New database table without `comment`.'
|
@@ -38,7 +39,7 @@ module RuboCop
|
|
38
39
|
|
39
40
|
# @!method comment_present?(node)
|
40
41
|
def_node_matcher :comment_present?, <<~PATTERN
|
41
|
-
(hash <(pair {(sym :comment) (str "comment")} (
|
42
|
+
(hash <(pair {(sym :comment) (str "comment")} !{nil (str blank?)}) ...>)
|
42
43
|
PATTERN
|
43
44
|
|
44
45
|
# @!method add_column?(node)
|
@@ -40,12 +40,13 @@ module RuboCop
|
|
40
40
|
autocorrect(corrector, select_node, node, preferred_method)
|
41
41
|
end
|
42
42
|
end
|
43
|
+
alias on_csend on_send
|
43
44
|
|
44
45
|
private
|
45
46
|
|
46
47
|
def find_select_node(node, column_name)
|
47
48
|
node.descendants.detect do |select_candidate|
|
48
|
-
next if !select_candidate.
|
49
|
+
next if !select_candidate.call_type? || !select_candidate.method?(:select)
|
49
50
|
|
50
51
|
match_column_name?(select_candidate, column_name)
|
51
52
|
end
|
@@ -53,7 +54,7 @@ module RuboCop
|
|
53
54
|
|
54
55
|
# rubocop:disable Metrics/AbcSize
|
55
56
|
def autocorrect(corrector, select_node, node, preferred_method)
|
56
|
-
corrector.remove(select_node.
|
57
|
+
corrector.remove(select_node.parent.loc.dot)
|
57
58
|
corrector.remove(select_node.loc.selector.begin.join(select_node.source_range.end))
|
58
59
|
corrector.replace(node.loc.selector.begin.join(node.source_range.end), preferred_method)
|
59
60
|
end
|
@@ -61,7 +61,7 @@ module RuboCop
|
|
61
61
|
def_node_matcher :good_touch?, <<~PATTERN
|
62
62
|
{
|
63
63
|
(send (const {nil? cbase} :FileUtils) :touch ...)
|
64
|
-
(send _ :touch
|
64
|
+
(send _ :touch boolean)
|
65
65
|
}
|
66
66
|
PATTERN
|
67
67
|
|
@@ -100,7 +100,8 @@ module RuboCop
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def forbidden_methods
|
103
|
-
|
103
|
+
# TODO: Remove when RuboCop Rails 3 releases.
|
104
|
+
obsolete_result = cop_config['Blacklist'] # rubocop:disable InternalAffairs/UndefinedConfig
|
104
105
|
if obsolete_result
|
105
106
|
warn '`Blacklist` has been renamed to `ForbiddenMethods`.' unless @displayed_forbidden_warning
|
106
107
|
@displayed_forbidden_warning = true
|
@@ -111,7 +112,8 @@ module RuboCop
|
|
111
112
|
end
|
112
113
|
|
113
114
|
def allowed_methods
|
114
|
-
|
115
|
+
# TODO: Remove when RuboCop Rails 3 releases.
|
116
|
+
obsolete_result = cop_config['Whitelist'] # rubocop:disable InternalAffairs/UndefinedConfig
|
115
117
|
if obsolete_result
|
116
118
|
warn '`Whitelist` has been renamed to `AllowedMethods`.' unless @displayed_allowed_warning
|
117
119
|
@displayed_allowed_warning = true
|