rubocop-rails 2.14.2 → 2.19.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/LICENSE.txt +1 -1
- data/README.md +23 -2
- data/config/default.yml +190 -12
- data/config/obsoletion.yml +10 -0
- data/lib/rubocop/cop/mixin/active_record_helper.rb +3 -6
- data/lib/rubocop/cop/mixin/active_record_migrations_helper.rb +1 -3
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +1 -1
- data/lib/rubocop/cop/mixin/index_method.rb +7 -17
- data/lib/rubocop/cop/mixin/migrations_helper.rb +1 -1
- data/lib/rubocop/cop/rails/action_controller_flash_before_render.rb +112 -0
- data/lib/rubocop/cop/rails/action_controller_test_case.rb +2 -2
- data/lib/rubocop/cop/rails/action_filter.rb +2 -2
- data/lib/rubocop/cop/rails/action_order.rb +116 -0
- data/lib/rubocop/cop/rails/active_record_aliases.rb +3 -4
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +7 -4
- data/lib/rubocop/cop/rails/active_record_override.rb +2 -5
- data/lib/rubocop/cop/rails/active_support_aliases.rb +1 -1
- data/lib/rubocop/cop/rails/active_support_on_load.rb +70 -0
- data/lib/rubocop/cop/rails/add_column_index.rb +3 -6
- data/lib/rubocop/cop/rails/after_commit_override.rb +1 -1
- data/lib/rubocop/cop/rails/application_controller.rb +2 -2
- data/lib/rubocop/cop/rails/application_job.rb +3 -3
- data/lib/rubocop/cop/rails/application_mailer.rb +2 -2
- data/lib/rubocop/cop/rails/application_record.rb +2 -2
- data/lib/rubocop/cop/rails/arel_star.rb +2 -2
- data/lib/rubocop/cop/rails/assert_not.rb +1 -1
- data/lib/rubocop/cop/rails/attribute_default_block_value.rb +1 -1
- data/lib/rubocop/cop/rails/belongs_to.rb +2 -5
- data/lib/rubocop/cop/rails/blank.rb +10 -11
- data/lib/rubocop/cop/rails/bulk_change_table.rb +8 -25
- data/lib/rubocop/cop/rails/compact_blank.rb +6 -2
- data/lib/rubocop/cop/rails/content_tag.rb +6 -7
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +16 -3
- data/lib/rubocop/cop/rails/date.rb +12 -17
- data/lib/rubocop/cop/rails/default_scope.rb +1 -1
- data/lib/rubocop/cop/rails/delegate.rb +24 -18
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +2 -2
- data/lib/rubocop/cop/rails/deprecated_active_model_errors_methods.rb +63 -3
- data/lib/rubocop/cop/rails/dot_separated_keys.rb +71 -0
- data/lib/rubocop/cop/rails/duplicate_association.rb +2 -2
- data/lib/rubocop/cop/rails/duplicate_scope.rb +1 -1
- data/lib/rubocop/cop/rails/duration_arithmetic.rb +4 -4
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +26 -14
- data/lib/rubocop/cop/rails/eager_evaluation_log_message.rb +6 -2
- data/lib/rubocop/cop/rails/enum_hash.rb +3 -4
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +3 -6
- data/lib/rubocop/cop/rails/environment_comparison.rb +3 -4
- data/lib/rubocop/cop/rails/environment_variable_access.rb +1 -1
- data/lib/rubocop/cop/rails/exit.rb +1 -1
- data/lib/rubocop/cop/rails/expanded_date_range.rb +39 -23
- data/lib/rubocop/cop/rails/file_path.rb +41 -24
- data/lib/rubocop/cop/rails/find_by.rb +1 -1
- data/lib/rubocop/cop/rails/find_by_id.rb +3 -3
- data/lib/rubocop/cop/rails/find_each.rb +14 -4
- data/lib/rubocop/cop/rails/freeze_time.rb +79 -0
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +1 -1
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +14 -8
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +3 -3
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +23 -12
- data/lib/rubocop/cop/rails/http_status.rb +6 -11
- data/lib/rubocop/cop/rails/i18n_lazy_lookup.rb +3 -1
- data/lib/rubocop/cop/rails/i18n_locale_assignment.rb +1 -1
- data/lib/rubocop/cop/rails/i18n_locale_texts.rb +2 -2
- data/lib/rubocop/cop/rails/ignored_columns_assignment.rb +50 -0
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +5 -14
- data/lib/rubocop/cop/rails/index_by.rb +2 -2
- data/lib/rubocop/cop/rails/index_with.rb +2 -2
- data/lib/rubocop/cop/rails/inquiry.rb +1 -1
- data/lib/rubocop/cop/rails/inverse_of.rb +4 -10
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +22 -16
- data/lib/rubocop/cop/rails/link_to_blank.rb +2 -5
- data/lib/rubocop/cop/rails/mailer_name.rb +5 -5
- data/lib/rubocop/cop/rails/match_route.rb +1 -1
- data/lib/rubocop/cop/rails/migration_class_name.rb +2 -2
- data/lib/rubocop/cop/rails/negate_include.rb +2 -2
- data/lib/rubocop/cop/rails/not_null_column.rb +10 -7
- data/lib/rubocop/cop/rails/order_by_id.rb +2 -3
- data/lib/rubocop/cop/rails/output.rb +7 -9
- data/lib/rubocop/cop/rails/output_safety.rb +6 -2
- data/lib/rubocop/cop/rails/pick.rb +1 -1
- data/lib/rubocop/cop/rails/pluck.rb +45 -13
- data/lib/rubocop/cop/rails/pluck_id.rb +2 -2
- data/lib/rubocop/cop/rails/pluck_in_where.rb +1 -1
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +2 -3
- data/lib/rubocop/cop/rails/presence.rb +22 -13
- data/lib/rubocop/cop/rails/present.rb +10 -13
- data/lib/rubocop/cop/rails/rake_environment.rb +3 -3
- data/lib/rubocop/cop/rails/read_write_attribute.rb +2 -2
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +5 -7
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +3 -3
- data/lib/rubocop/cop/rails/redundant_presence_validation_on_belongs_to.rb +3 -3
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +31 -27
- data/lib/rubocop/cop/rails/redundant_travel_back.rb +1 -1
- data/lib/rubocop/cop/rails/reflection_class_name.rb +35 -2
- data/lib/rubocop/cop/rails/refute_methods.rb +1 -5
- data/lib/rubocop/cop/rails/relative_date_constant.rb +5 -8
- data/lib/rubocop/cop/rails/render_inline.rb +1 -1
- data/lib/rubocop/cop/rails/render_plain_text.rb +1 -1
- data/lib/rubocop/cop/rails/request_referer.rb +2 -3
- data/lib/rubocop/cop/rails/require_dependency.rb +2 -2
- data/lib/rubocop/cop/rails/response_parsed_body.rb +57 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +15 -63
- data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +5 -6
- data/lib/rubocop/cop/rails/root_join_chain.rb +1 -1
- data/lib/rubocop/cop/rails/root_pathname_methods.rb +238 -0
- data/lib/rubocop/cop/rails/root_public_path.rb +59 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +8 -13
- data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +2 -4
- data/lib/rubocop/cop/rails/save_bang.rb +12 -24
- data/lib/rubocop/cop/rails/schema_comment.rb +1 -1
- data/lib/rubocop/cop/rails/scope_args.rb +1 -1
- data/lib/rubocop/cop/rails/short_i18n.rb +3 -6
- data/lib/rubocop/cop/rails/skips_model_validations.rb +3 -4
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +10 -7
- data/lib/rubocop/cop/rails/strip_heredoc.rb +56 -0
- data/lib/rubocop/cop/rails/table_name_assignment.rb +1 -1
- data/lib/rubocop/cop/rails/three_state_boolean_column.rb +73 -0
- data/lib/rubocop/cop/rails/time_zone.rb +34 -32
- data/lib/rubocop/cop/rails/time_zone_assignment.rb +4 -4
- data/lib/rubocop/cop/rails/to_formatted_s.rb +46 -0
- data/lib/rubocop/cop/rails/to_s_with_argument.rb +78 -0
- data/lib/rubocop/cop/rails/top_level_hash_with_indifferent_access.rb +49 -0
- data/lib/rubocop/cop/rails/transaction_exit_statement.rb +17 -12
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +3 -6
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +14 -7
- data/lib/rubocop/cop/rails/unknown_env.rb +3 -5
- data/lib/rubocop/cop/rails/unused_ignored_columns.rb +7 -2
- data/lib/rubocop/cop/rails/validation.rb +5 -13
- data/lib/rubocop/cop/rails/where_equals.rb +2 -2
- data/lib/rubocop/cop/rails/where_exists.rb +3 -3
- data/lib/rubocop/cop/rails/where_missing.rb +118 -0
- data/lib/rubocop/cop/rails/where_not.rb +2 -2
- data/lib/rubocop/cop/rails/where_not_with_multiple_conditions.rb +55 -0
- data/lib/rubocop/cop/rails_cops.rb +16 -0
- data/lib/rubocop/rails/schema_loader/schema.rb +8 -5
- data/lib/rubocop/rails/version.rb +1 -1
- data/lib/rubocop/rails.rb +1 -1
- data/lib/rubocop-rails.rb +19 -0
- metadata +23 -9
- data/bin/console +0 -11
- data/bin/setup +0 -7
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Looks for `has_many` or `has_one` associations that don't
|
7
7
|
# specify a `:dependent` option.
|
8
8
|
#
|
9
9
|
# It doesn't register an offense if `:through` or `dependent: nil`
|
@@ -37,15 +37,15 @@ module RuboCop
|
|
37
37
|
RESTRICT_ON_SEND = %i[has_many has_one].freeze
|
38
38
|
|
39
39
|
def_node_search :active_resource_class?, <<~PATTERN
|
40
|
-
(const (const nil? :ActiveResource) :Base)
|
40
|
+
(const (const {nil? cbase} :ActiveResource) :Base)
|
41
41
|
PATTERN
|
42
42
|
|
43
43
|
def_node_matcher :association_without_options?, <<~PATTERN
|
44
|
-
(send
|
44
|
+
(send _ {:has_many :has_one} _)
|
45
45
|
PATTERN
|
46
46
|
|
47
47
|
def_node_matcher :association_with_options?, <<~PATTERN
|
48
|
-
(send
|
48
|
+
(send _ {:has_many :has_one} ... (hash $...))
|
49
49
|
PATTERN
|
50
50
|
|
51
51
|
def_node_matcher :dependent_option?, <<~PATTERN
|
@@ -105,9 +105,7 @@ module RuboCop
|
|
105
105
|
|
106
106
|
return false unless node.parent
|
107
107
|
|
108
|
-
return true if contain_valid_options_in_with_options_block?(
|
109
|
-
node.parent.parent
|
110
|
-
)
|
108
|
+
return true if contain_valid_options_in_with_options_block?(node.parent.parent)
|
111
109
|
end
|
112
110
|
|
113
111
|
false
|
@@ -116,7 +114,7 @@ module RuboCop
|
|
116
114
|
def valid_options?(options)
|
117
115
|
return false if options.nil?
|
118
116
|
|
119
|
-
options = options
|
117
|
+
options = extract_option_if_kwsplat(options)
|
120
118
|
|
121
119
|
return true unless options
|
122
120
|
return true if options.any? do |o|
|
@@ -126,6 +124,14 @@ module RuboCop
|
|
126
124
|
false
|
127
125
|
end
|
128
126
|
|
127
|
+
def extract_option_if_kwsplat(options)
|
128
|
+
if options.first.kwsplat_type? && options.first.children.first.hash_type?
|
129
|
+
return options.first.children.first.pairs
|
130
|
+
end
|
131
|
+
|
132
|
+
options
|
133
|
+
end
|
134
|
+
|
129
135
|
def active_resource?(node)
|
130
136
|
return false if node.nil?
|
131
137
|
|
@@ -3,14 +3,14 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Checks for use of the helper methods which reference
|
7
7
|
# instance variables.
|
8
8
|
#
|
9
9
|
# Relying on instance variables makes it difficult to re-use helper
|
10
10
|
# methods.
|
11
11
|
#
|
12
12
|
# If it seems awkward to explicitly pass in each dependent
|
13
|
-
# variable, consider moving the
|
13
|
+
# variable, consider moving the behavior elsewhere, for
|
14
14
|
# example to a model, decorator or presenter.
|
15
15
|
#
|
16
16
|
# Provided that a class inherits `ActionView::Helpers::FormBuilder`,
|
@@ -37,7 +37,7 @@ module RuboCop
|
|
37
37
|
def_node_matcher :form_builder_class?, <<~PATTERN
|
38
38
|
(const
|
39
39
|
(const
|
40
|
-
(const nil? :ActionView) :Helpers) :FormBuilder)
|
40
|
+
(const {nil? cbase} :ActionView) :Helpers) :FormBuilder)
|
41
41
|
PATTERN
|
42
42
|
|
43
43
|
def on_ivar(node)
|
@@ -3,13 +3,16 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Identifies usages of http methods like `get`, `post`,
|
7
7
|
# `put`, `patch` without the usage of keyword arguments in your tests and
|
8
8
|
# change them to use keyword args. This cop only applies to Rails >= 5.
|
9
9
|
# If you are running Rails < 5 you should disable the
|
10
10
|
# Rails/HttpPositionalArguments cop or set your TargetRailsVersion in your
|
11
11
|
# .rubocop.yml file to 4.2.
|
12
12
|
#
|
13
|
+
# NOTE: It does not detect any cases where `include Rack::Test::Methods` is used
|
14
|
+
# which makes the http methods incompatible behavior.
|
15
|
+
#
|
13
16
|
# @example
|
14
17
|
# # bad
|
15
18
|
# get :new, { user_id: 1}
|
@@ -22,11 +25,8 @@ module RuboCop
|
|
22
25
|
extend AutoCorrector
|
23
26
|
extend TargetRailsVersion
|
24
27
|
|
25
|
-
MSG = 'Use keyword arguments instead of '
|
26
|
-
|
27
|
-
KEYWORD_ARGS = %i[
|
28
|
-
method params session body flash xhr as headers env to
|
29
|
-
].freeze
|
28
|
+
MSG = 'Use keyword arguments instead of positional arguments for http call: `%<verb>s`.'
|
29
|
+
KEYWORD_ARGS = %i[method params session body flash xhr as headers env to].freeze
|
30
30
|
ROUTING_METHODS = %i[draw routes].freeze
|
31
31
|
RESTRICT_ON_SEND = %i[get post put patch delete head].freeze
|
32
32
|
|
@@ -40,8 +40,15 @@ module RuboCop
|
|
40
40
|
(hash (kwsplat _))
|
41
41
|
PATTERN
|
42
42
|
|
43
|
+
def_node_matcher :include_rack_test_methods?, <<~PATTERN
|
44
|
+
(send nil? :include
|
45
|
+
(const
|
46
|
+
(const
|
47
|
+
(const {nil? cbase} :Rack) :Test) :Methods))
|
48
|
+
PATTERN
|
49
|
+
|
43
50
|
def on_send(node)
|
44
|
-
return if in_routing_block?(node)
|
51
|
+
return if in_routing_block?(node) || use_rack_test_methods?
|
45
52
|
|
46
53
|
http_request?(node) do |data|
|
47
54
|
return unless needs_conversion?(data)
|
@@ -59,7 +66,7 @@ module RuboCop
|
|
59
66
|
# that represents the path/action on the Rails controller
|
60
67
|
# the data is the http parameters and environment sent in
|
61
68
|
# the Rails 5 http call
|
62
|
-
corrector.replace(node
|
69
|
+
corrector.replace(node, correction(node))
|
63
70
|
end
|
64
71
|
end
|
65
72
|
end
|
@@ -70,13 +77,18 @@ module RuboCop
|
|
70
77
|
!!node.each_ancestor(:block).detect { |block| ROUTING_METHODS.include?(block.method_name) }
|
71
78
|
end
|
72
79
|
|
80
|
+
def use_rack_test_methods?
|
81
|
+
processed_source.ast.each_descendant(:send).any? do |node|
|
82
|
+
include_rack_test_methods?(node)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
73
86
|
def needs_conversion?(data)
|
74
87
|
return true unless data.hash_type?
|
75
88
|
return false if kwsplat_hash?(data)
|
76
89
|
|
77
90
|
data.each_pair.none? do |pair|
|
78
|
-
special_keyword_arg?(pair.key) ||
|
79
|
-
(format_arg?(pair.key) && data.pairs.one?)
|
91
|
+
special_keyword_arg?(pair.key) || (format_arg?(pair.key) && data.pairs.one?)
|
80
92
|
end
|
81
93
|
end
|
82
94
|
|
@@ -98,8 +110,7 @@ module RuboCop
|
|
98
110
|
return '' if data.hash_type? && data.empty?
|
99
111
|
|
100
112
|
hash_data = if data.hash_type?
|
101
|
-
format('{ %<data>s }',
|
102
|
-
data: data.pairs.map(&:source).join(', '))
|
113
|
+
format('{ %<data>s }', data: data.pairs.map(&:source).join(', '))
|
103
114
|
else
|
104
115
|
# user supplies an object,
|
105
116
|
# no need to surround with braces
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
66
66
|
return unless checker.offensive?
|
67
67
|
|
68
68
|
add_offense(checker.node, message: checker.message) do |corrector|
|
69
|
-
corrector.replace(checker.node
|
69
|
+
corrector.replace(checker.node, checker.preferred_style)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -84,10 +84,8 @@ module RuboCop
|
|
84
84
|
|
85
85
|
# :nodoc:
|
86
86
|
class SymbolicStyleChecker
|
87
|
-
MSG = 'Prefer `%<prefer>s` over `%<current>s` '
|
88
|
-
|
89
|
-
DEFAULT_MSG = 'Prefer `symbolic` over `numeric` ' \
|
90
|
-
'to define HTTP status code.'
|
87
|
+
MSG = 'Prefer `%<prefer>s` over `%<current>s` to define HTTP status code.'
|
88
|
+
DEFAULT_MSG = 'Prefer `symbolic` over `numeric` to define HTTP status code.'
|
91
89
|
|
92
90
|
attr_reader :node
|
93
91
|
|
@@ -118,17 +116,14 @@ module RuboCop
|
|
118
116
|
end
|
119
117
|
|
120
118
|
def custom_http_status_code?
|
121
|
-
node.int_type? &&
|
122
|
-
!::Rack::Utils::SYMBOL_TO_STATUS_CODE.value?(number)
|
119
|
+
node.int_type? && !::Rack::Utils::SYMBOL_TO_STATUS_CODE.value?(number)
|
123
120
|
end
|
124
121
|
end
|
125
122
|
|
126
123
|
# :nodoc:
|
127
124
|
class NumericStyleChecker
|
128
|
-
MSG = 'Prefer `%<prefer>s` over `%<current>s` '
|
129
|
-
|
130
|
-
DEFAULT_MSG = 'Prefer `numeric` over `symbolic` ' \
|
131
|
-
'to define HTTP status code.'
|
125
|
+
MSG = 'Prefer `%<prefer>s` over `%<current>s` to define HTTP status code.'
|
126
|
+
DEFAULT_MSG = 'Prefer `numeric` over `symbolic` to define HTTP status code.'
|
132
127
|
PERMITTED_STATUS = %i[error success missing redirect].freeze
|
133
128
|
|
134
129
|
attr_reader :node
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Checks for places where I18n "lazy" lookup can be used.
|
7
7
|
#
|
8
8
|
# @example
|
9
9
|
# # en.yml
|
@@ -34,6 +34,8 @@ module RuboCop
|
|
34
34
|
|
35
35
|
MSG = 'Use "lazy" lookup for the text used in controllers.'
|
36
36
|
|
37
|
+
RESTRICT_ON_SEND = %i[translate t].freeze
|
38
|
+
|
37
39
|
def_node_matcher :translate_call?, <<~PATTERN
|
38
40
|
(send nil? {:translate :t} ${sym_type? str_type?} ...)
|
39
41
|
PATTERN
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Checks for the use of `I18n.locale=` method.
|
7
7
|
#
|
8
8
|
# The `locale` attribute persists for the rest of the Ruby runtime, potentially causing
|
9
9
|
# unexpected behavior at a later time.
|
@@ -69,7 +69,7 @@ module RuboCop
|
|
69
69
|
class I18nLocaleTexts < Base
|
70
70
|
MSG = 'Move locale texts to the locale files in the `config/locales` directory.'
|
71
71
|
|
72
|
-
RESTRICT_ON_SEND = %i[validates redirect_to []= mail].freeze
|
72
|
+
RESTRICT_ON_SEND = %i[validates redirect_to redirect_back []= mail].freeze
|
73
73
|
|
74
74
|
def_node_search :validation_message, <<~PATTERN
|
75
75
|
(pair (sym :message) $str)
|
@@ -94,7 +94,7 @@ module RuboCop
|
|
94
94
|
add_offense(text_node)
|
95
95
|
end
|
96
96
|
return
|
97
|
-
when :redirect_to
|
97
|
+
when :redirect_to, :redirect_back
|
98
98
|
text_node = redirect_to_flash(node).to_a.last
|
99
99
|
when :[]=
|
100
100
|
text_node = flash_assignment?(node)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# Looks for assignments of `ignored_columns` that may override previous
|
7
|
+
# assignments.
|
8
|
+
#
|
9
|
+
# Overwriting previous assignments is usually a mistake, since it will
|
10
|
+
# un-ignore the first set of columns. Since duplicate column names is not
|
11
|
+
# a problem, it is better to simply append to the list.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# class User < ActiveRecord::Base
|
17
|
+
# self.ignored_columns = [:one]
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# # bad
|
21
|
+
# class User < ActiveRecord::Base
|
22
|
+
# self.ignored_columns = [:one, :two]
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# class User < ActiveRecord::Base
|
27
|
+
# self.ignored_columns += [:one, :two]
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# # good
|
31
|
+
# class User < ActiveRecord::Base
|
32
|
+
# self.ignored_columns += [:one]
|
33
|
+
# self.ignored_columns += [:two]
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
class IgnoredColumnsAssignment < Base
|
37
|
+
extend AutoCorrector
|
38
|
+
|
39
|
+
MSG = 'Use `+=` instead of `=`.'
|
40
|
+
RESTRICT_ON_SEND = %i[ignored_columns=].freeze
|
41
|
+
|
42
|
+
def on_send(node)
|
43
|
+
add_offense(node.loc.operator) do |corrector|
|
44
|
+
corrector.replace(node.loc.operator, '+=')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Checks that `if` and `only` (or `except`) are not used together
|
7
7
|
# as options of `skip_*` action filter.
|
8
8
|
#
|
9
9
|
# The `if` option will be ignored when `if` and `only` are used together.
|
@@ -35,19 +35,12 @@ module RuboCop
|
|
35
35
|
# skip_before_action :login_required,
|
36
36
|
# if: -> { trusted_origin? && action_name != "admin" }
|
37
37
|
# end
|
38
|
-
#
|
39
|
-
# @see https://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html#method-i-_normalize_callback_options
|
40
38
|
class IgnoredSkipActionFilterOption < Base
|
41
39
|
MSG = <<~MSG.chomp.freeze
|
42
40
|
`%<ignore>s` option will be ignored when `%<prefer>s` and `%<ignore>s` are used together.
|
43
41
|
MSG
|
44
42
|
|
45
|
-
RESTRICT_ON_SEND = %i[
|
46
|
-
skip_after_action
|
47
|
-
skip_around_action
|
48
|
-
skip_before_action
|
49
|
-
skip_action_callback
|
50
|
-
].freeze
|
43
|
+
RESTRICT_ON_SEND = %i[skip_after_action skip_around_action skip_before_action skip_action_callback].freeze
|
51
44
|
|
52
45
|
FILTERS = RESTRICT_ON_SEND.map { |method_name| ":#{method_name}" }
|
53
46
|
|
@@ -67,11 +60,9 @@ module RuboCop
|
|
67
60
|
options = options_hash(options)
|
68
61
|
|
69
62
|
if if_and_only?(options)
|
70
|
-
add_offense(options[:if],
|
71
|
-
message: format(MSG, prefer: :only, ignore: :if))
|
63
|
+
add_offense(options[:if], message: format(MSG, prefer: :only, ignore: :if))
|
72
64
|
elsif if_and_except?(options)
|
73
|
-
add_offense(options[:except],
|
74
|
-
message: format(MSG, prefer: :if, ignore: :except))
|
65
|
+
add_offense(options[:except], message: format(MSG, prefer: :if, ignore: :except))
|
75
66
|
end
|
76
67
|
end
|
77
68
|
|
@@ -80,7 +71,7 @@ module RuboCop
|
|
80
71
|
def options_hash(options)
|
81
72
|
options.pairs
|
82
73
|
.select { |pair| pair.key.sym_type? }
|
83
|
-
.
|
74
|
+
.to_h { |pair| [pair.key.value, pair] }
|
84
75
|
end
|
85
76
|
|
86
77
|
def if_and_only?(options)
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Looks for uses of `each_with_object({}) { ... }`,
|
7
7
|
# `map { ... }.to_h`, and `Hash[map { ... }]` that are transforming
|
8
8
|
# an enumerable into a hash where the values are the original elements.
|
9
9
|
# Rails provides the `index_by` method for this purpose.
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
46
46
|
|
47
47
|
def_node_matcher :on_bad_hash_brackets_map, <<~PATTERN
|
48
48
|
(send
|
49
|
-
(const
|
49
|
+
(const {nil? cbase} :Hash)
|
50
50
|
:[]
|
51
51
|
(block
|
52
52
|
(call _ {:map :collect})
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Looks for uses of `each_with_object({}) { ... }`,
|
7
7
|
# `map { ... }.to_h`, and `Hash[map { ... }]` that are transforming
|
8
8
|
# an enumerable into a hash where the keys are the original elements.
|
9
9
|
# Rails provides the `index_with` method for this purpose.
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
|
50
50
|
def_node_matcher :on_bad_hash_brackets_map, <<~PATTERN
|
51
51
|
(send
|
52
|
-
(const
|
52
|
+
(const {nil? cbase} :Hash)
|
53
53
|
:[]
|
54
54
|
(block
|
55
55
|
(call _ {:map :collect})
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Looks for has_(one|many) and belongs_to associations where
|
7
7
|
# Active Record can't automatically determine the inverse association
|
8
8
|
# because of a scope or the options used. Using the blog with order scope
|
9
9
|
# example below, traversing the a Blog's association in both directions
|
@@ -137,9 +137,6 @@ module RuboCop
|
|
137
137
|
# class Blog < ApplicationRecord
|
138
138
|
# has_many :posts, -> { order(published_at: :desc) }
|
139
139
|
# end
|
140
|
-
#
|
141
|
-
# @see https://guides.rubyonrails.org/association_basics.html#bi-directional-associations
|
142
|
-
# @see https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#module-ActiveRecord::Associations::ClassMethods-label-Setting+Inverses
|
143
140
|
class InverseOf < Base
|
144
141
|
SPECIFY_MSG = 'Specify an `:inverse_of` option.'
|
145
142
|
NIL_MSG = 'You specified `inverse_of: nil`, you probably meant to use `inverse_of: false`.'
|
@@ -192,8 +189,7 @@ module RuboCop
|
|
192
189
|
end
|
193
190
|
return if options_ignoring_inverse_of?(options)
|
194
191
|
|
195
|
-
return unless scope?(arguments) ||
|
196
|
-
options_requiring_inverse_of?(options)
|
192
|
+
return unless scope?(arguments) || options_requiring_inverse_of?(options)
|
197
193
|
|
198
194
|
return if options_contain_inverse_of?(options)
|
199
195
|
|
@@ -206,8 +202,7 @@ module RuboCop
|
|
206
202
|
|
207
203
|
def options_requiring_inverse_of?(options)
|
208
204
|
required = options.any? do |opt|
|
209
|
-
conditions_option?(opt) ||
|
210
|
-
foreign_key_option?(opt)
|
205
|
+
conditions_option?(opt) || foreign_key_option?(opt)
|
211
206
|
end
|
212
207
|
|
213
208
|
return required if target_rails_version >= 5.2
|
@@ -227,8 +222,7 @@ module RuboCop
|
|
227
222
|
|
228
223
|
def with_options_arguments(recv, node)
|
229
224
|
blocks = node.each_ancestor(:block).select do |block|
|
230
|
-
block.send_node.command?(:with_options) &&
|
231
|
-
same_context_in_with_options?(block.arguments.first, recv)
|
225
|
+
block.send_node.command?(:with_options) && same_context_in_with_options?(block.arguments.first, recv)
|
232
226
|
end
|
233
227
|
blocks.flat_map { |n| n.send_node.arguments }
|
234
228
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Checks that methods specified in the filter's `only` or
|
7
7
|
# `except` options are defined within the same class or module.
|
8
8
|
#
|
9
9
|
# @safety
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
12
12
|
# methods that are defined in other classes or modules, you should
|
13
13
|
# define the filter in that class or module.
|
14
14
|
#
|
15
|
-
# If you rely on
|
15
|
+
# If you rely on behavior defined in the superclass actions, you must
|
16
16
|
# remember to invoke `super` in the subclass actions.
|
17
17
|
#
|
18
18
|
# @example
|
@@ -71,7 +71,7 @@ module RuboCop
|
|
71
71
|
# class ArticlesController < ContentController
|
72
72
|
# before_action :load_article, only: [:update]
|
73
73
|
#
|
74
|
-
# # the cop requires this method, but it relies on
|
74
|
+
# # the cop requires this method, but it relies on behavior defined
|
75
75
|
# # in the superclass, so needs to invoke `super`
|
76
76
|
# def update
|
77
77
|
# super
|
@@ -144,19 +144,29 @@ module RuboCop
|
|
144
144
|
end
|
145
145
|
|
146
146
|
def aliased_action_methods(node, defined_methods)
|
147
|
-
alias_methods = node
|
148
|
-
|
149
|
-
hash_of_alias_methods = alias_methods.each_with_object({}) do |alias_method, result|
|
150
|
-
result[alias_method.last_argument.value] = alias_method.first_argument.value
|
151
|
-
end
|
152
|
-
|
147
|
+
alias_methods = alias_methods(node)
|
153
148
|
defined_methods.each_with_object([]) do |defined_method, aliased_method|
|
154
|
-
if (new_method_name =
|
149
|
+
if (new_method_name = alias_methods[defined_method])
|
155
150
|
aliased_method << new_method_name
|
156
151
|
end
|
157
152
|
end
|
158
153
|
end
|
159
154
|
|
155
|
+
def alias_methods(node)
|
156
|
+
result = {}
|
157
|
+
node.each_child_node(:send, :alias) do |child_node|
|
158
|
+
case child_node.type
|
159
|
+
when :send
|
160
|
+
if child_node.method?(:alias_method)
|
161
|
+
result[child_node.last_argument.value] = child_node.first_argument.value
|
162
|
+
end
|
163
|
+
when :alias
|
164
|
+
result[child_node.old_identifier.value] = child_node.new_identifier.value
|
165
|
+
end
|
166
|
+
end
|
167
|
+
result
|
168
|
+
end
|
169
|
+
|
160
170
|
# @param node [RuboCop::AST::Node]
|
161
171
|
# @return [Array<Symbol>]
|
162
172
|
def array_values(node) # rubocop:disable Metrics/MethodLength
|
@@ -184,13 +194,9 @@ module RuboCop
|
|
184
194
|
# @return [String]
|
185
195
|
def message(methods, parent)
|
186
196
|
if methods.size == 1
|
187
|
-
format(MSG,
|
188
|
-
action: "`#{methods[0]}` is",
|
189
|
-
type: parent.type)
|
197
|
+
format(MSG, action: "`#{methods[0]}` is", type: parent.type)
|
190
198
|
else
|
191
|
-
format(MSG,
|
192
|
-
action: "`#{methods.join('`, `')}` are",
|
193
|
-
type: parent.type)
|
199
|
+
format(MSG, action: "`#{methods.join('`, `')}` are", type: parent.type)
|
194
200
|
end
|
195
201
|
end
|
196
202
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Checks for calls to `link_to` that contain a
|
7
7
|
# `target: '_blank'` but no `rel: 'noopener'`. This can be a security
|
8
8
|
# risk as the loaded page will have control over the previous page
|
9
9
|
# and could change its location for phishing purposes.
|
@@ -68,10 +68,7 @@ module RuboCop
|
|
68
68
|
|
69
69
|
def append_to_rel(rel_node, corrector)
|
70
70
|
existing_rel = rel_node.children.last.value
|
71
|
-
str_range = rel_node.children.last.
|
72
|
-
begin_pos: 1,
|
73
|
-
end_pos: -1
|
74
|
-
)
|
71
|
+
str_range = rel_node.children.last.source_range.adjust(begin_pos: 1, end_pos: -1)
|
75
72
|
corrector.replace(str_range, "#{existing_rel} noopener")
|
76
73
|
end
|
77
74
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Enforces that mailer names end with `Mailer` suffix.
|
7
7
|
#
|
8
8
|
# Without the `Mailer` suffix it isn't immediately apparent what's a mailer
|
9
9
|
# and which views are related to the mailer.
|
@@ -34,8 +34,8 @@ module RuboCop
|
|
34
34
|
|
35
35
|
def_node_matcher :mailer_base_class?, <<~PATTERN
|
36
36
|
{
|
37
|
-
(const (const nil? :ActionMailer) :Base)
|
38
|
-
(const nil? :ApplicationMailer)
|
37
|
+
(const (const {nil? cbase} :ActionMailer) :Base)
|
38
|
+
(const {nil? cbase} :ApplicationMailer)
|
39
39
|
}
|
40
40
|
PATTERN
|
41
41
|
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
PATTERN
|
45
45
|
|
46
46
|
def_node_matcher :class_new_definition?, <<~PATTERN
|
47
|
-
(send (const nil? :Class) :new #mailer_base_class?)
|
47
|
+
(send (const {nil? cbase} :Class) :new #mailer_base_class?)
|
48
48
|
PATTERN
|
49
49
|
|
50
50
|
def on_class(node)
|
@@ -77,7 +77,7 @@ module RuboCop
|
|
77
77
|
corrector.replace(node.loc.name, "#{name}Mailer")
|
78
78
|
else
|
79
79
|
name = node.children.last
|
80
|
-
corrector.replace(node
|
80
|
+
corrector.replace(node, "#{name}Mailer")
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Identifies places where defining routes with `match`
|
7
7
|
# can be replaced with a specific HTTP method.
|
8
8
|
#
|
9
9
|
# Don't use `match` to define any routes unless there is a need to map multiple request types
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Makes sure that each migration file defines a migration class
|
7
7
|
# whose name matches the file name.
|
8
8
|
# (e.g. `20220224111111_create_users.rb` should define `CreateUsers` class.)
|
9
9
|
#
|
@@ -29,7 +29,7 @@ module RuboCop
|
|
29
29
|
|
30
30
|
basename = basename_without_timestamp_and_suffix(processed_source.file_path)
|
31
31
|
|
32
|
-
class_identifier = node.identifier
|
32
|
+
class_identifier = node.identifier.location.name
|
33
33
|
camelized_basename = camelize(basename)
|
34
34
|
return if class_identifier.source.casecmp(camelized_basename).zero?
|
35
35
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
#
|
6
|
+
# Enforces the use of `collection.exclude?(obj)`
|
7
7
|
# over `!collection.include?(obj)`.
|
8
8
|
#
|
9
9
|
# @safety
|
@@ -26,7 +26,7 @@ module RuboCop
|
|
26
26
|
RESTRICT_ON_SEND = %i[!].freeze
|
27
27
|
|
28
28
|
def_node_matcher :negate_include_call?, <<~PATTERN
|
29
|
-
(send (send
|
29
|
+
(send (send $!nil? :include? $_) :!)
|
30
30
|
PATTERN
|
31
31
|
|
32
32
|
def on_send(node)
|