rubocop-rails 2.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +92 -0
- data/bin/setup +7 -0
- data/config/default.yml +510 -0
- data/lib/rubocop-rails.rb +12 -0
- data/lib/rubocop/cop/mixin/target_rails_version.rb +16 -0
- data/lib/rubocop/cop/rails/action_filter.rb +111 -0
- data/lib/rubocop/cop/rails/active_record_aliases.rb +48 -0
- data/lib/rubocop/cop/rails/active_record_override.rb +82 -0
- data/lib/rubocop/cop/rails/active_support_aliases.rb +69 -0
- data/lib/rubocop/cop/rails/application_controller.rb +36 -0
- data/lib/rubocop/cop/rails/application_job.rb +40 -0
- data/lib/rubocop/cop/rails/application_mailer.rb +40 -0
- data/lib/rubocop/cop/rails/application_record.rb +40 -0
- data/lib/rubocop/cop/rails/assert_not.rb +44 -0
- data/lib/rubocop/cop/rails/belongs_to.rb +102 -0
- data/lib/rubocop/cop/rails/blank.rb +164 -0
- data/lib/rubocop/cop/rails/bulk_change_table.rb +293 -0
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +91 -0
- data/lib/rubocop/cop/rails/date.rb +161 -0
- data/lib/rubocop/cop/rails/delegate.rb +132 -0
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +37 -0
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +91 -0
- data/lib/rubocop/cop/rails/enum_hash.rb +75 -0
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +65 -0
- data/lib/rubocop/cop/rails/environment_comparison.rb +68 -0
- data/lib/rubocop/cop/rails/exit.rb +67 -0
- data/lib/rubocop/cop/rails/file_path.rb +108 -0
- data/lib/rubocop/cop/rails/find_by.rb +55 -0
- data/lib/rubocop/cop/rails/find_each.rb +51 -0
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +25 -0
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +106 -0
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +39 -0
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +117 -0
- data/lib/rubocop/cop/rails/http_status.rb +160 -0
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +94 -0
- data/lib/rubocop/cop/rails/inverse_of.rb +246 -0
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +175 -0
- data/lib/rubocop/cop/rails/link_to_blank.rb +98 -0
- data/lib/rubocop/cop/rails/not_null_column.rb +67 -0
- data/lib/rubocop/cop/rails/output.rb +49 -0
- data/lib/rubocop/cop/rails/output_safety.rb +99 -0
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +107 -0
- data/lib/rubocop/cop/rails/presence.rb +148 -0
- data/lib/rubocop/cop/rails/present.rb +153 -0
- data/lib/rubocop/cop/rails/rake_environment.rb +91 -0
- data/lib/rubocop/cop/rails/read_write_attribute.rb +74 -0
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +111 -0
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +136 -0
- data/lib/rubocop/cop/rails/reflection_class_name.rb +37 -0
- data/lib/rubocop/cop/rails/refute_methods.rb +76 -0
- data/lib/rubocop/cop/rails/relative_date_constant.rb +102 -0
- data/lib/rubocop/cop/rails/request_referer.rb +56 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +284 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +85 -0
- data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +48 -0
- data/lib/rubocop/cop/rails/save_bang.rb +331 -0
- data/lib/rubocop/cop/rails/scope_args.rb +29 -0
- data/lib/rubocop/cop/rails/skips_model_validations.rb +87 -0
- data/lib/rubocop/cop/rails/time_zone.rb +249 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +105 -0
- data/lib/rubocop/cop/rails/unknown_env.rb +84 -0
- data/lib/rubocop/cop/rails/validation.rb +147 -0
- data/lib/rubocop/cop/rails_cops.rb +61 -0
- data/lib/rubocop/rails.rb +12 -0
- data/lib/rubocop/rails/inject.rb +18 -0
- data/lib/rubocop/rails/version.rb +10 -0
- metadata +148 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop looks for enums written with array syntax.
|
7
|
+
#
|
8
|
+
# When using array syntax, adding an element in a
|
9
|
+
# position other than the last causes all previous
|
10
|
+
# definitions to shift. Explicitly specifying the
|
11
|
+
# value for each key prevents this from happening.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # bad
|
15
|
+
# enum status: [:active, :archived]
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# enum status: { active: 0, archived: 1 }
|
19
|
+
#
|
20
|
+
class EnumHash < Cop
|
21
|
+
MSG = 'Enum defined as an array found in `%<enum>s` enum declaration. '\
|
22
|
+
'Use hash syntax instead.'
|
23
|
+
|
24
|
+
def_node_matcher :enum?, <<~PATTERN
|
25
|
+
(send nil? :enum (hash $...))
|
26
|
+
PATTERN
|
27
|
+
|
28
|
+
def_node_matcher :array_pair?, <<~PATTERN
|
29
|
+
(pair $_ $array)
|
30
|
+
PATTERN
|
31
|
+
|
32
|
+
def on_send(node)
|
33
|
+
enum?(node) do |pairs|
|
34
|
+
pairs.each do |pair|
|
35
|
+
key, array = array_pair?(pair)
|
36
|
+
next unless key
|
37
|
+
|
38
|
+
add_offense(array, message: format(MSG, enum: enum_name(key)))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def autocorrect(node)
|
44
|
+
hash = node.children.each_with_index.map do |elem, index|
|
45
|
+
"#{source(elem)} => #{index}"
|
46
|
+
end.join(', ')
|
47
|
+
|
48
|
+
->(corrector) { corrector.replace(node.loc.expression, "{#{hash}}") }
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def enum_name(key)
|
54
|
+
case key.type
|
55
|
+
when :sym, :str
|
56
|
+
key.value
|
57
|
+
else
|
58
|
+
key.source
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def source(elem)
|
63
|
+
case elem.type
|
64
|
+
when :str
|
65
|
+
elem.value.dump
|
66
|
+
when :sym
|
67
|
+
elem.value.inspect
|
68
|
+
else
|
69
|
+
elem.source
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop looks for duplicate values in enum declarations.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# enum status: { active: 0, archived: 0 }
|
11
|
+
#
|
12
|
+
# # good
|
13
|
+
# enum status: { active: 0, archived: 1 }
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# enum status: [:active, :archived, :active]
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# enum status: [:active, :archived]
|
20
|
+
class EnumUniqueness < Cop
|
21
|
+
include Duplication
|
22
|
+
|
23
|
+
MSG = 'Duplicate value `%<value>s` found in `%<enum>s` ' \
|
24
|
+
'enum declaration.'
|
25
|
+
|
26
|
+
def_node_matcher :enum?, <<~PATTERN
|
27
|
+
(send nil? :enum (hash $...))
|
28
|
+
PATTERN
|
29
|
+
|
30
|
+
def_node_matcher :enum_values, <<~PATTERN
|
31
|
+
(pair $_ ${array hash})
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def on_send(node)
|
35
|
+
enum?(node) do |pairs|
|
36
|
+
pairs.each do |pair|
|
37
|
+
enum_values(pair) do |key, args|
|
38
|
+
items = args.values
|
39
|
+
|
40
|
+
next unless duplicates?(items)
|
41
|
+
|
42
|
+
consecutive_duplicates(items).each do |item|
|
43
|
+
add_offense(item, message: format(
|
44
|
+
MSG, value: item.source, enum: enum_name(key)
|
45
|
+
))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def enum_name(key)
|
55
|
+
case key.type
|
56
|
+
when :sym, :str
|
57
|
+
key.value
|
58
|
+
else
|
59
|
+
key.source
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks that Rails.env is compared using `.production?`-like
|
7
|
+
# methods instead of equality against a string or symbol.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# Rails.env == 'production'
|
12
|
+
#
|
13
|
+
# # bad, always returns false
|
14
|
+
# Rails.env == :test
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# Rails.env.production?
|
18
|
+
class EnvironmentComparison < Cop
|
19
|
+
MSG = "Favor `Rails.env.%<env>s?` over `Rails.env == '%<env>s'`."
|
20
|
+
|
21
|
+
SYM_MSG = 'Do not compare `Rails.env` with a symbol, it will always ' \
|
22
|
+
'evaluate to `false`.'
|
23
|
+
|
24
|
+
def_node_matcher :environment_str_comparison?, <<~PATTERN
|
25
|
+
(send
|
26
|
+
(send (const {nil? cbase} :Rails) :env)
|
27
|
+
:==
|
28
|
+
$str
|
29
|
+
)
|
30
|
+
PATTERN
|
31
|
+
|
32
|
+
def_node_matcher :environment_sym_comparison?, <<~PATTERN
|
33
|
+
(send
|
34
|
+
(send (const {nil? cbase} :Rails) :env)
|
35
|
+
:==
|
36
|
+
$sym
|
37
|
+
)
|
38
|
+
PATTERN
|
39
|
+
|
40
|
+
def on_send(node)
|
41
|
+
environment_str_comparison?(node) do |env_node|
|
42
|
+
env, = *env_node
|
43
|
+
add_offense(node, message: format(MSG, env: env))
|
44
|
+
end
|
45
|
+
environment_sym_comparison?(node) do |_|
|
46
|
+
add_offense(node, message: SYM_MSG)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def autocorrect(node)
|
51
|
+
lambda do |corrector|
|
52
|
+
corrector.replace(node.source_range, replacement(node))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def replacement(node)
|
59
|
+
"#{node.receiver.source}.#{content(node.first_argument)}?"
|
60
|
+
end
|
61
|
+
|
62
|
+
def_node_matcher :content, <<~PATTERN
|
63
|
+
({str sym} $_)
|
64
|
+
PATTERN
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop enforces that `exit` calls are not used within a rails app.
|
7
|
+
# Valid options are instead to raise an error, break, return, or some
|
8
|
+
# other form of stopping execution of current request.
|
9
|
+
#
|
10
|
+
# There are two obvious cases where `exit` is particularly harmful:
|
11
|
+
#
|
12
|
+
# - Usage in library code for your application. Even though Rails will
|
13
|
+
# rescue from a `SystemExit` and continue on, unit testing that library
|
14
|
+
# code will result in specs exiting (potentially silently if `exit(0)`
|
15
|
+
# is used.)
|
16
|
+
# - Usage in application code outside of the web process could result in
|
17
|
+
# the program exiting, which could result in the code failing to run and
|
18
|
+
# do its job.
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# # bad
|
22
|
+
# exit(0)
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# raise 'a bad error has happened'
|
26
|
+
class Exit < Cop
|
27
|
+
include ConfigurableEnforcedStyle
|
28
|
+
|
29
|
+
MSG = 'Do not use `exit` in Rails applications.'
|
30
|
+
TARGET_METHODS = %i[exit exit!].freeze
|
31
|
+
EXPLICIT_RECEIVERS = %i[Kernel Process].freeze
|
32
|
+
|
33
|
+
def on_send(node)
|
34
|
+
add_offense(node, location: :selector) if offending_node?(node)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def offending_node?(node)
|
40
|
+
right_method_name?(node.method_name) &&
|
41
|
+
right_argument_count?(node.arguments) &&
|
42
|
+
right_receiver?(node.receiver)
|
43
|
+
end
|
44
|
+
|
45
|
+
def right_method_name?(method_name)
|
46
|
+
TARGET_METHODS.include?(method_name)
|
47
|
+
end
|
48
|
+
|
49
|
+
# More than 1 argument likely means it is a different
|
50
|
+
# `exit` implementation than the one we are preventing.
|
51
|
+
def right_argument_count?(arg_nodes)
|
52
|
+
arg_nodes.size <= 1
|
53
|
+
end
|
54
|
+
|
55
|
+
# Only register if exit is being called explicitly on `Kernel`,
|
56
|
+
# `Process`, or if receiver node is nil for plain `exit` calls.
|
57
|
+
def right_receiver?(receiver_node)
|
58
|
+
return true unless receiver_node
|
59
|
+
|
60
|
+
_a, receiver_node_class, _c = *receiver_node
|
61
|
+
|
62
|
+
EXPLICIT_RECEIVERS.include?(receiver_node_class)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop is used to identify usages of file path joining process
|
7
|
+
# to use `Rails.root.join` clause. It is used to add uniformity when
|
8
|
+
# joining paths.
|
9
|
+
#
|
10
|
+
# @example EnforcedStyle: arguments
|
11
|
+
# # bad
|
12
|
+
# Rails.root.join('app/models/goober')
|
13
|
+
# File.join(Rails.root, 'app/models/goober')
|
14
|
+
# "#{Rails.root}/app/models/goober"
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# Rails.root.join('app', 'models', 'goober')
|
18
|
+
#
|
19
|
+
# @example EnforcedStyle: slashes (default)
|
20
|
+
# # bad
|
21
|
+
# Rails.root.join('app', 'models', 'goober')
|
22
|
+
# File.join(Rails.root, 'app/models/goober')
|
23
|
+
# "#{Rails.root}/app/models/goober"
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# Rails.root.join('app/models/goober')
|
27
|
+
#
|
28
|
+
class FilePath < Cop
|
29
|
+
include ConfigurableEnforcedStyle
|
30
|
+
include RangeHelp
|
31
|
+
|
32
|
+
MSG_SLASHES = 'Please use `Rails.root.join(\'path/to\')` ' \
|
33
|
+
'instead.'
|
34
|
+
MSG_ARGUMENTS = 'Please use `Rails.root.join(\'path\', \'to\')` ' \
|
35
|
+
'instead.'
|
36
|
+
|
37
|
+
def_node_matcher :file_join_nodes?, <<~PATTERN
|
38
|
+
(send (const nil? :File) :join ...)
|
39
|
+
PATTERN
|
40
|
+
|
41
|
+
def_node_search :rails_root_nodes?, <<~PATTERN
|
42
|
+
(send (const nil? :Rails) :root)
|
43
|
+
PATTERN
|
44
|
+
|
45
|
+
def_node_matcher :rails_root_join_nodes?, <<~PATTERN
|
46
|
+
(send (send (const nil? :Rails) :root) :join ...)
|
47
|
+
PATTERN
|
48
|
+
|
49
|
+
def on_dstr(node)
|
50
|
+
return unless rails_root_nodes?(node)
|
51
|
+
return unless node.children.last.source.start_with?('.') ||
|
52
|
+
node.children.last.source.include?(File::SEPARATOR)
|
53
|
+
|
54
|
+
register_offense(node)
|
55
|
+
end
|
56
|
+
|
57
|
+
def on_send(node)
|
58
|
+
check_for_file_join_with_rails_root(node)
|
59
|
+
check_for_rails_root_join_with_slash_separated_path(node)
|
60
|
+
check_for_rails_root_join_with_string_arguments(node)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def check_for_file_join_with_rails_root(node)
|
66
|
+
return unless file_join_nodes?(node)
|
67
|
+
return unless node.arguments.any? { |e| rails_root_nodes?(e) }
|
68
|
+
|
69
|
+
register_offense(node)
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_for_rails_root_join_with_string_arguments(node)
|
73
|
+
return unless style == :slashes
|
74
|
+
return unless rails_root_nodes?(node)
|
75
|
+
return unless rails_root_join_nodes?(node)
|
76
|
+
return unless node.arguments.size > 1
|
77
|
+
return unless node.arguments.all?(&:str_type?)
|
78
|
+
|
79
|
+
register_offense(node)
|
80
|
+
end
|
81
|
+
|
82
|
+
def check_for_rails_root_join_with_slash_separated_path(node)
|
83
|
+
return unless style == :arguments
|
84
|
+
return unless rails_root_nodes?(node)
|
85
|
+
return unless rails_root_join_nodes?(node)
|
86
|
+
return unless node.arguments.any? { |arg| string_with_slash?(arg) }
|
87
|
+
|
88
|
+
register_offense(node)
|
89
|
+
end
|
90
|
+
|
91
|
+
def string_with_slash?(node)
|
92
|
+
node.str_type? && node.source =~ %r{/}
|
93
|
+
end
|
94
|
+
|
95
|
+
def register_offense(node)
|
96
|
+
line_range = node.loc.column...node.loc.last_column
|
97
|
+
source_range = source_range(processed_source.buffer, node.first_line,
|
98
|
+
line_range)
|
99
|
+
add_offense(node, location: source_range)
|
100
|
+
end
|
101
|
+
|
102
|
+
def message(_node)
|
103
|
+
format(style == :arguments ? MSG_ARGUMENTS : MSG_SLASHES)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop is used to identify usages of `where.first` and
|
7
|
+
# change them to use `find_by` instead.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# User.where(name: 'Bruce').first
|
12
|
+
# User.where(name: 'Bruce').take
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# User.find_by(name: 'Bruce')
|
16
|
+
class FindBy < Cop
|
17
|
+
include RangeHelp
|
18
|
+
|
19
|
+
MSG = 'Use `find_by` instead of `where.%<method>s`.'
|
20
|
+
TARGET_SELECTORS = %i[first take].freeze
|
21
|
+
|
22
|
+
def_node_matcher :where_first?, <<~PATTERN
|
23
|
+
(send ({send csend} _ :where ...) {:first :take})
|
24
|
+
PATTERN
|
25
|
+
|
26
|
+
def on_send(node)
|
27
|
+
return unless where_first?(node)
|
28
|
+
|
29
|
+
range = range_between(node.receiver.loc.selector.begin_pos,
|
30
|
+
node.loc.selector.end_pos)
|
31
|
+
|
32
|
+
add_offense(node, location: range,
|
33
|
+
message: format(MSG, method: node.method_name))
|
34
|
+
end
|
35
|
+
alias on_csend on_send
|
36
|
+
|
37
|
+
def autocorrect(node)
|
38
|
+
# Don't autocorrect where(...).first, because it can return different
|
39
|
+
# results from find_by. (They order records differently, so the
|
40
|
+
# 'first' record can be different.)
|
41
|
+
return if node.method?(:first)
|
42
|
+
|
43
|
+
where_loc = node.receiver.loc.selector
|
44
|
+
first_loc = range_between(node.loc.dot.begin_pos,
|
45
|
+
node.loc.selector.end_pos)
|
46
|
+
|
47
|
+
lambda do |corrector|
|
48
|
+
corrector.replace(where_loc, 'find_by')
|
49
|
+
corrector.replace(first_loc, '')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop is used to identify usages of `all.each` and
|
7
|
+
# change them to use `all.find_each` instead.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# User.all.each
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# User.all.find_each
|
15
|
+
class FindEach < Cop
|
16
|
+
MSG = 'Use `find_each` instead of `each`.'
|
17
|
+
|
18
|
+
SCOPE_METHODS = %i[
|
19
|
+
all eager_load includes joins left_joins left_outer_joins not preload
|
20
|
+
references unscoped where
|
21
|
+
].freeze
|
22
|
+
IGNORED_METHODS = %i[order limit select].freeze
|
23
|
+
|
24
|
+
def on_send(node)
|
25
|
+
return unless node.receiver&.send_type? &&
|
26
|
+
node.method?(:each)
|
27
|
+
|
28
|
+
return unless SCOPE_METHODS.include?(node.receiver.method_name)
|
29
|
+
return if method_chain(node).any? { |m| ignored_by_find_each?(m) }
|
30
|
+
|
31
|
+
add_offense(node, location: :selector)
|
32
|
+
end
|
33
|
+
|
34
|
+
def autocorrect(node)
|
35
|
+
->(corrector) { corrector.replace(node.loc.selector, 'find_each') }
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def method_chain(node)
|
41
|
+
node.each_node(:send).map(&:method_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def ignored_by_find_each?(relation_method)
|
45
|
+
# Active Record's #find_each ignores various extra parameters
|
46
|
+
IGNORED_METHODS.include?(relation_method)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|