rubocop-rails 2.0.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 +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +73 -0
- data/bin/setup +7 -0
- data/config/default.yml +466 -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 +117 -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_job.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 +289 -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_uniqueness.rb +45 -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 +124 -0
- data/lib/rubocop/cop/rails/present.rb +153 -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 +93 -0
- data/lib/rubocop/cop/rails/request_referer.rb +56 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +286 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +87 -0
- data/lib/rubocop/cop/rails/save_bang.rb +316 -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 +238 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +105 -0
- data/lib/rubocop/cop/rails/unknown_env.rb +63 -0
- data/lib/rubocop/cop/rails/validation.rb +109 -0
- data/lib/rubocop/cop/rails_cops.rb +64 -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 +143 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks the migration for which timestamps are not included
|
7
|
+
# when creating a new table.
|
8
|
+
# In many cases, timestamps are useful information and should be added.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# create_table :users
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# create_table :users do |t|
|
16
|
+
# t.string :name
|
17
|
+
# t.string :email
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# create_table :users do |t|
|
22
|
+
# t.string :name
|
23
|
+
# t.string :email
|
24
|
+
#
|
25
|
+
# t.timestamps
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# # good
|
29
|
+
# create_table :users do |t|
|
30
|
+
# t.string :name
|
31
|
+
# t.string :email
|
32
|
+
#
|
33
|
+
# t.datetime :created_at, default: -> { 'CURRENT_TIMESTAMP' }
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # good
|
37
|
+
# create_table :users do |t|
|
38
|
+
# t.string :name
|
39
|
+
# t.string :email
|
40
|
+
#
|
41
|
+
# t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP' }
|
42
|
+
# end
|
43
|
+
class CreateTableWithTimestamps < Cop
|
44
|
+
MSG = 'Add timestamps when creating a new table.'
|
45
|
+
|
46
|
+
def_node_matcher :create_table_with_block?, <<-PATTERN
|
47
|
+
(block
|
48
|
+
(send nil? :create_table ...)
|
49
|
+
(args (arg _var))
|
50
|
+
_)
|
51
|
+
PATTERN
|
52
|
+
|
53
|
+
def_node_matcher :create_table_with_timestamps_proc?, <<-PATTERN
|
54
|
+
(send nil? :create_table (sym _) ... (block-pass (sym :timestamps)))
|
55
|
+
PATTERN
|
56
|
+
|
57
|
+
def_node_search :timestamps_included?, <<-PATTERN
|
58
|
+
(send _var :timestamps ...)
|
59
|
+
PATTERN
|
60
|
+
|
61
|
+
def_node_search :created_at_or_updated_at_included?, <<-PATTERN
|
62
|
+
(send _var :datetime
|
63
|
+
{(sym {:created_at :updated_at})(str {"created_at" "updated_at"})}
|
64
|
+
...)
|
65
|
+
PATTERN
|
66
|
+
|
67
|
+
def on_send(node)
|
68
|
+
return unless node.command?(:create_table)
|
69
|
+
|
70
|
+
parent = node.parent
|
71
|
+
|
72
|
+
if create_table_with_block?(parent)
|
73
|
+
if parent.body.nil? || !time_columns_included?(parent.body)
|
74
|
+
add_offense(parent)
|
75
|
+
end
|
76
|
+
elsif create_table_with_timestamps_proc?(node)
|
77
|
+
# nothing to do
|
78
|
+
else
|
79
|
+
add_offense(node)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def time_columns_included?(node)
|
86
|
+
timestamps_included?(node) || created_at_or_updated_at_included?(node)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks for the correct use of Date methods,
|
7
|
+
# such as Date.today, Date.current etc.
|
8
|
+
#
|
9
|
+
# Using `Date.today` is dangerous, because it doesn't know anything about
|
10
|
+
# Rails time zone. You must use `Time.zone.today` instead.
|
11
|
+
#
|
12
|
+
# The cop also reports warnings when you are using `to_time` method,
|
13
|
+
# because it doesn't know about Rails time zone either.
|
14
|
+
#
|
15
|
+
# Two styles are supported for this cop. When EnforcedStyle is 'strict'
|
16
|
+
# then the Date methods `today`, `current`, `yesterday`, and `tomorrow`
|
17
|
+
# are prohibited and the usage of both `to_time`
|
18
|
+
# and 'to_time_in_current_zone' are reported as warning.
|
19
|
+
#
|
20
|
+
# When EnforcedStyle is 'flexible' then only `Date.today` is prohibited
|
21
|
+
# and only `to_time` is reported as warning.
|
22
|
+
#
|
23
|
+
# @example EnforcedStyle: strict
|
24
|
+
# # bad
|
25
|
+
# Date.current
|
26
|
+
# Date.yesterday
|
27
|
+
# Date.today
|
28
|
+
# date.to_time
|
29
|
+
#
|
30
|
+
# # good
|
31
|
+
# Time.zone.today
|
32
|
+
# Time.zone.today - 1.day
|
33
|
+
#
|
34
|
+
# @example EnforcedStyle: flexible (default)
|
35
|
+
# # bad
|
36
|
+
# Date.today
|
37
|
+
# date.to_time
|
38
|
+
#
|
39
|
+
# # good
|
40
|
+
# Time.zone.today
|
41
|
+
# Time.zone.today - 1.day
|
42
|
+
# Date.current
|
43
|
+
# Date.yesterday
|
44
|
+
# date.in_time_zone
|
45
|
+
#
|
46
|
+
class Date < Cop
|
47
|
+
include ConfigurableEnforcedStyle
|
48
|
+
|
49
|
+
MSG = 'Do not use `Date.%<method_called>s` without zone. Use ' \
|
50
|
+
'`Time.zone.%<day>s` instead.'
|
51
|
+
|
52
|
+
MSG_SEND = 'Do not use `%<method>s` on Date objects, because they ' \
|
53
|
+
'know nothing about the time zone in use.'
|
54
|
+
|
55
|
+
BAD_DAYS = %i[today current yesterday tomorrow].freeze
|
56
|
+
|
57
|
+
DEPRECATED_METHODS = [
|
58
|
+
{ deprecated: 'to_time_in_current_zone', relevant: 'in_time_zone' }
|
59
|
+
].freeze
|
60
|
+
|
61
|
+
DEPRECATED_MSG = '`%<deprecated>s` is deprecated. ' \
|
62
|
+
'Use `%<relevant>s` instead.'
|
63
|
+
|
64
|
+
def on_const(node)
|
65
|
+
mod, klass = *node.children
|
66
|
+
# we should only check core Date class (`Date` or `::Date`)
|
67
|
+
return unless (mod.nil? || mod.cbase_type?) && method_send?(node)
|
68
|
+
|
69
|
+
check_date_node(node.parent) if klass == :Date
|
70
|
+
end
|
71
|
+
|
72
|
+
def on_send(node)
|
73
|
+
return unless node.receiver && bad_methods.include?(node.method_name)
|
74
|
+
|
75
|
+
return if safe_chain?(node) || safe_to_time?(node)
|
76
|
+
|
77
|
+
check_deprecated_methods(node)
|
78
|
+
|
79
|
+
add_offense(node, location: :selector,
|
80
|
+
message: format(MSG_SEND, method: node.method_name))
|
81
|
+
end
|
82
|
+
alias on_csend on_send
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def check_deprecated_methods(node)
|
87
|
+
DEPRECATED_METHODS.each do |relevant:, deprecated:|
|
88
|
+
next unless node.method_name == deprecated.to_sym
|
89
|
+
|
90
|
+
add_offense(node, location: :selector,
|
91
|
+
message: format(DEPRECATED_MSG,
|
92
|
+
deprecated: deprecated,
|
93
|
+
relevant: relevant))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def check_date_node(node)
|
98
|
+
chain = extract_method_chain(node)
|
99
|
+
|
100
|
+
return if (chain & bad_days).empty?
|
101
|
+
|
102
|
+
method_name = (chain & bad_days).join('.')
|
103
|
+
|
104
|
+
day = method_name
|
105
|
+
day = 'today' if method_name == 'current'
|
106
|
+
|
107
|
+
add_offense(node, location: :selector,
|
108
|
+
message: format(MSG,
|
109
|
+
method_called: method_name,
|
110
|
+
day: day))
|
111
|
+
end
|
112
|
+
|
113
|
+
def extract_method_chain(node)
|
114
|
+
[node, *node.each_ancestor(:send)].map(&:method_name)
|
115
|
+
end
|
116
|
+
|
117
|
+
# checks that parent node of send_type
|
118
|
+
# and receiver is the given node
|
119
|
+
def method_send?(node)
|
120
|
+
return false unless node.parent&.send_type?
|
121
|
+
|
122
|
+
node.parent.receiver == node
|
123
|
+
end
|
124
|
+
|
125
|
+
def safe_chain?(node)
|
126
|
+
chain = extract_method_chain(node)
|
127
|
+
|
128
|
+
(chain & bad_methods).empty? || !(chain & good_methods).empty?
|
129
|
+
end
|
130
|
+
|
131
|
+
def safe_to_time?(node)
|
132
|
+
return unless node.method?(:to_time)
|
133
|
+
|
134
|
+
if node.receiver.str_type?
|
135
|
+
zone_regexp = /([+-][\d:]+|\dZ)\z/
|
136
|
+
|
137
|
+
node.receiver.str_content.match(zone_regexp)
|
138
|
+
else
|
139
|
+
node.arguments.one?
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def good_days
|
144
|
+
style == :strict ? [] : %i[current yesterday tomorrow]
|
145
|
+
end
|
146
|
+
|
147
|
+
def bad_days
|
148
|
+
BAD_DAYS - good_days
|
149
|
+
end
|
150
|
+
|
151
|
+
def bad_methods
|
152
|
+
%i[to_time to_time_in_current_zone]
|
153
|
+
end
|
154
|
+
|
155
|
+
def good_methods
|
156
|
+
style == :strict ? [] : TimeZone::ACCEPTED_METHODS
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop looks for delegations that could have been created
|
7
|
+
# automatically with the `delegate` method.
|
8
|
+
#
|
9
|
+
# Safe navigation `&.` is ignored because Rails' `allow_nil`
|
10
|
+
# option checks not just for nil but also delegates if nil
|
11
|
+
# responds to the delegated method.
|
12
|
+
#
|
13
|
+
# The `EnforceForPrefixed` option (defaulted to `true`) means that
|
14
|
+
# using the target object as a prefix of the method name
|
15
|
+
# without using the `delegate` method will be a violation.
|
16
|
+
# When set to `false`, this case is legal.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# # bad
|
20
|
+
# def bar
|
21
|
+
# foo.bar
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
# delegate :bar, to: :foo
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# def bar
|
29
|
+
# foo&.bar
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # good
|
33
|
+
# private
|
34
|
+
# def bar
|
35
|
+
# foo.bar
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# @example EnforceForPrefixed: true (default)
|
39
|
+
# # bad
|
40
|
+
# def foo_bar
|
41
|
+
# foo.bar
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# delegate :bar, to: :foo, prefix: true
|
46
|
+
#
|
47
|
+
# @example EnforceForPrefixed: false
|
48
|
+
# # good
|
49
|
+
# def foo_bar
|
50
|
+
# foo.bar
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# # good
|
54
|
+
# delegate :bar, to: :foo, prefix: true
|
55
|
+
class Delegate < Cop
|
56
|
+
MSG = 'Use `delegate` to define delegations.'
|
57
|
+
|
58
|
+
def_node_matcher :delegate?, <<-PATTERN
|
59
|
+
(def _method_name _args
|
60
|
+
(send (send nil? _) _ ...))
|
61
|
+
PATTERN
|
62
|
+
|
63
|
+
def on_def(node)
|
64
|
+
return unless trivial_delegate?(node)
|
65
|
+
return if private_or_protected_delegation(node)
|
66
|
+
|
67
|
+
add_offense(node, location: :keyword)
|
68
|
+
end
|
69
|
+
|
70
|
+
def autocorrect(node)
|
71
|
+
delegation = ["delegate :#{node.body.method_name}",
|
72
|
+
"to: :#{node.body.receiver.method_name}"]
|
73
|
+
|
74
|
+
if node.method_name == prefixed_method_name(node.body)
|
75
|
+
delegation << ['prefix: true']
|
76
|
+
end
|
77
|
+
|
78
|
+
lambda do |corrector|
|
79
|
+
corrector.replace(node.source_range, delegation.join(', '))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def trivial_delegate?(def_node)
|
86
|
+
delegate?(def_node) &&
|
87
|
+
method_name_matches?(def_node.method_name, def_node.body) &&
|
88
|
+
arguments_match?(def_node.arguments, def_node.body)
|
89
|
+
end
|
90
|
+
|
91
|
+
def arguments_match?(arg_array, body)
|
92
|
+
argument_array = body.arguments
|
93
|
+
|
94
|
+
return false if arg_array.size != argument_array.size
|
95
|
+
|
96
|
+
arg_array.zip(argument_array).all? do |arg, argument|
|
97
|
+
arg.arg_type? &&
|
98
|
+
argument.lvar_type? &&
|
99
|
+
arg.children == argument.children
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def method_name_matches?(method_name, body)
|
104
|
+
method_name == body.method_name ||
|
105
|
+
include_prefix_case? && method_name == prefixed_method_name(body)
|
106
|
+
end
|
107
|
+
|
108
|
+
def include_prefix_case?
|
109
|
+
cop_config['EnforceForPrefixed']
|
110
|
+
end
|
111
|
+
|
112
|
+
def prefixed_method_name(body)
|
113
|
+
[body.receiver.method_name, body.method_name].join('_').to_sym
|
114
|
+
end
|
115
|
+
|
116
|
+
def private_or_protected_delegation(node)
|
117
|
+
line = node.first_line
|
118
|
+
private_or_protected_before(line) ||
|
119
|
+
private_or_protected_inline(line)
|
120
|
+
end
|
121
|
+
|
122
|
+
def private_or_protected_before(line)
|
123
|
+
(processed_source[0..line].map(&:strip) & %w[private protected]).any?
|
124
|
+
end
|
125
|
+
|
126
|
+
def private_or_protected_inline(line)
|
127
|
+
processed_source[line - 1].strip =~ /\A(private )|(protected )/
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop looks for delegations that pass :allow_blank as an option
|
7
|
+
# instead of :allow_nil. :allow_blank is not a valid option to pass
|
8
|
+
# to ActiveSupport#delegate.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# delegate :foo, to: :bar, allow_blank: true
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# delegate :foo, to: :bar, allow_nil: true
|
16
|
+
class DelegateAllowBlank < Cop
|
17
|
+
MSG = '`allow_blank` is not a valid option, use `allow_nil`.'
|
18
|
+
|
19
|
+
def_node_matcher :allow_blank_option, <<-PATTERN
|
20
|
+
(send nil? :delegate _ (hash <$(pair (sym :allow_blank) true) ...>))
|
21
|
+
PATTERN
|
22
|
+
|
23
|
+
def on_send(node)
|
24
|
+
allow_blank_option(node) do |offending_node|
|
25
|
+
add_offense(offending_node)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def autocorrect(pair_node)
|
30
|
+
lambda do |corrector|
|
31
|
+
corrector.replace(pair_node.key.source_range, 'allow_nil')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop checks dynamic `find_by_*` methods.
|
7
|
+
# Use `find_by` instead of dynamic method.
|
8
|
+
# See. https://github.com/rubocop-hq/rails-style-guide#find_by
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# User.find_by_name(name)
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# User.find_by_name_and_email(name)
|
16
|
+
#
|
17
|
+
# # bad
|
18
|
+
# User.find_by_email!(name)
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# User.find_by(name: name)
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# User.find_by(name: name, email: email)
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# User.find_by!(email: email)
|
28
|
+
class DynamicFindBy < Cop
|
29
|
+
MSG = 'Use `%<static_name>s` instead of dynamic `%<method>s`.'
|
30
|
+
METHOD_PATTERN = /^find_by_(.+?)(!)?$/.freeze
|
31
|
+
|
32
|
+
def on_send(node)
|
33
|
+
method_name = node.method_name.to_s
|
34
|
+
|
35
|
+
return if whitelist.include?(method_name)
|
36
|
+
|
37
|
+
static_name = static_method_name(method_name)
|
38
|
+
|
39
|
+
return unless static_name
|
40
|
+
|
41
|
+
add_offense(node,
|
42
|
+
message: format(MSG, static_name: static_name,
|
43
|
+
method: node.method_name))
|
44
|
+
end
|
45
|
+
alias on_csend on_send
|
46
|
+
|
47
|
+
def autocorrect(node)
|
48
|
+
keywords = column_keywords(node.method_name)
|
49
|
+
|
50
|
+
return if keywords.size != node.arguments.size
|
51
|
+
|
52
|
+
lambda do |corrector|
|
53
|
+
autocorrect_method_name(corrector, node)
|
54
|
+
autocorrect_argument_keywords(corrector, node, keywords)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def autocorrect_method_name(corrector, node)
|
61
|
+
corrector.replace(node.loc.selector,
|
62
|
+
static_method_name(node.method_name.to_s))
|
63
|
+
end
|
64
|
+
|
65
|
+
def autocorrect_argument_keywords(corrector, node, keywords)
|
66
|
+
keywords.each.with_index do |keyword, idx|
|
67
|
+
corrector.insert_before(node.arguments[idx].loc.expression, keyword)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def whitelist
|
72
|
+
cop_config['Whitelist']
|
73
|
+
end
|
74
|
+
|
75
|
+
def column_keywords(method)
|
76
|
+
keyword_string = method.to_s[METHOD_PATTERN, 1]
|
77
|
+
keyword_string.split('_and_').map { |keyword| "#{keyword}: " }
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns static method name.
|
81
|
+
# If code isn't wrong, returns nil
|
82
|
+
def static_method_name(method_name)
|
83
|
+
match = METHOD_PATTERN.match(method_name)
|
84
|
+
return nil unless match
|
85
|
+
|
86
|
+
match[2] ? 'find_by!' : 'find_by'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|