rubocop-rails 2.7.1 → 2.10.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 +18 -2
- data/config/default.yml +144 -6
- data/config/obsoletion.yml +7 -0
- data/lib/rubocop/cop/mixin/active_record_helper.rb +16 -3
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
- data/lib/rubocop/cop/mixin/index_method.rb +25 -11
- data/lib/rubocop/cop/rails/action_filter.rb +10 -14
- data/lib/rubocop/cop/rails/active_record_aliases.rb +13 -17
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +19 -16
- data/lib/rubocop/cop/rails/active_record_override.rb +1 -1
- data/lib/rubocop/cop/rails/active_support_aliases.rb +12 -21
- data/lib/rubocop/cop/rails/after_commit_override.rb +91 -0
- data/lib/rubocop/cop/rails/application_controller.rb +3 -7
- data/lib/rubocop/cop/rails/application_job.rb +2 -1
- data/lib/rubocop/cop/rails/application_mailer.rb +2 -7
- data/lib/rubocop/cop/rails/application_record.rb +2 -7
- data/lib/rubocop/cop/rails/arel_star.rb +41 -0
- data/lib/rubocop/cop/rails/assert_not.rb +8 -10
- data/lib/rubocop/cop/rails/attribute_default_block_value.rb +90 -0
- data/lib/rubocop/cop/rails/belongs_to.rb +10 -19
- data/lib/rubocop/cop/rails/blank.rb +31 -27
- data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
- data/lib/rubocop/cop/rails/content_tag.rb +34 -19
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -1
- data/lib/rubocop/cop/rails/date.rb +10 -11
- data/lib/rubocop/cop/rails/default_scope.rb +11 -4
- data/lib/rubocop/cop/rails/delegate.rb +9 -9
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +15 -12
- data/lib/rubocop/cop/rails/enum_hash.rb +11 -10
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -1
- data/lib/rubocop/cop/rails/environment_comparison.rb +18 -14
- data/lib/rubocop/cop/rails/environment_variable_access.rb +67 -0
- data/lib/rubocop/cop/rails/exit.rb +4 -10
- data/lib/rubocop/cop/rails/file_path.rb +7 -8
- data/lib/rubocop/cop/rails/find_by.rb +13 -13
- data/lib/rubocop/cop/rails/find_by_id.rb +12 -21
- data/lib/rubocop/cop/rails/find_each.rb +19 -18
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +37 -10
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +30 -2
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +32 -21
- data/lib/rubocop/cop/rails/http_status.rb +7 -9
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +8 -6
- data/lib/rubocop/cop/rails/index_by.rb +11 -2
- data/lib/rubocop/cop/rails/index_with.rb +11 -2
- data/lib/rubocop/cop/rails/inquiry.rb +7 -2
- data/lib/rubocop/cop/rails/inverse_of.rb +3 -2
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -15
- data/lib/rubocop/cop/rails/link_to_blank.rb +25 -23
- data/lib/rubocop/cop/rails/mailer_name.rb +19 -13
- data/lib/rubocop/cop/rails/match_route.rb +14 -13
- data/lib/rubocop/cop/rails/negate_include.rb +10 -8
- data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
- data/lib/rubocop/cop/rails/order_by_id.rb +52 -0
- data/lib/rubocop/cop/rails/output.rb +5 -2
- data/lib/rubocop/cop/rails/output_safety.rb +3 -2
- data/lib/rubocop/cop/rails/pick.rb +14 -12
- data/lib/rubocop/cop/rails/pluck.rb +6 -9
- data/lib/rubocop/cop/rails/pluck_id.rb +4 -6
- data/lib/rubocop/cop/rails/pluck_in_where.rb +39 -5
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +10 -14
- data/lib/rubocop/cop/rails/presence.rb +12 -13
- data/lib/rubocop/cop/rails/present.rb +30 -24
- data/lib/rubocop/cop/rails/rake_environment.rb +8 -10
- data/lib/rubocop/cop/rails/read_write_attribute.rb +12 -11
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +29 -31
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +9 -12
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +11 -10
- data/lib/rubocop/cop/rails/reflection_class_name.rb +18 -4
- data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
- data/lib/rubocop/cop/rails/relative_date_constant.rb +34 -22
- data/lib/rubocop/cop/rails/render_inline.rb +2 -1
- data/lib/rubocop/cop/rails/render_plain_text.rb +9 -14
- data/lib/rubocop/cop/rails/request_referer.rb +7 -7
- data/lib/rubocop/cop/rails/require_dependency.rb +38 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +83 -8
- data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +75 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +30 -11
- data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
- data/lib/rubocop/cop/rails/save_bang.rb +19 -22
- data/lib/rubocop/cop/rails/scope_args.rb +2 -1
- data/lib/rubocop/cop/rails/short_i18n.rb +7 -9
- data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -4
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +82 -0
- data/lib/rubocop/cop/rails/time_zone.rb +35 -25
- data/lib/rubocop/cop/rails/time_zone_assignment.rb +37 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +6 -6
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +18 -8
- data/lib/rubocop/cop/rails/unknown_env.rb +3 -3
- data/lib/rubocop/cop/rails/validation.rb +15 -14
- data/lib/rubocop/cop/rails/where_equals.rb +98 -0
- data/lib/rubocop/cop/rails/where_exists.rb +85 -16
- data/lib/rubocop/cop/rails/where_not.rb +101 -0
- data/lib/rubocop/cop/rails_cops.rb +12 -0
- data/lib/rubocop/rails.rb +2 -0
- data/lib/rubocop/rails/schema_loader.rb +4 -4
- data/lib/rubocop/rails/schema_loader/schema.rb +4 -8
- data/lib/rubocop/rails/version.rb +5 -1
- metadata +33 -14
@@ -32,7 +32,9 @@ module RuboCop
|
|
32
32
|
# validates :foo, size: true
|
33
33
|
# validates :foo, uniqueness: true
|
34
34
|
#
|
35
|
-
class Validation <
|
35
|
+
class Validation < Base
|
36
|
+
extend AutoCorrector
|
37
|
+
|
36
38
|
MSG = 'Prefer the new style validations `%<prefer>s` over ' \
|
37
39
|
'`%<current>s`.'
|
38
40
|
|
@@ -50,22 +52,20 @@ module RuboCop
|
|
50
52
|
uniqueness
|
51
53
|
].freeze
|
52
54
|
|
53
|
-
|
55
|
+
RESTRICT_ON_SEND = TYPES.map { |p| "validates_#{p}_of".to_sym }.freeze
|
54
56
|
ALLOWLIST = TYPES.map { |p| "validates :column, #{p}: value" }.freeze
|
55
57
|
|
56
58
|
def on_send(node)
|
57
|
-
return
|
59
|
+
return if node.receiver
|
58
60
|
|
59
|
-
|
60
|
-
end
|
61
|
+
range = node.loc.selector
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
add_offense(range, message: message(node)) do |corrector|
|
64
|
+
last_argument = node.arguments.last
|
65
|
+
return if !last_argument.literal? && !last_argument.splat_type? &&
|
66
|
+
!frozen_array_argument?(last_argument)
|
66
67
|
|
67
|
-
|
68
|
-
corrector.replace(node.loc.selector, 'validates')
|
68
|
+
corrector.replace(range, 'validates')
|
69
69
|
correct_validate_type(corrector, node)
|
70
70
|
end
|
71
71
|
end
|
@@ -73,12 +73,13 @@ module RuboCop
|
|
73
73
|
private
|
74
74
|
|
75
75
|
def message(node)
|
76
|
-
|
77
|
-
|
76
|
+
method_name = node.method_name
|
77
|
+
|
78
|
+
format(MSG, prefer: preferred_method(method_name), current: method_name)
|
78
79
|
end
|
79
80
|
|
80
81
|
def preferred_method(method)
|
81
|
-
ALLOWLIST[
|
82
|
+
ALLOWLIST[RESTRICT_ON_SEND.index(method.to_sym)]
|
82
83
|
end
|
83
84
|
|
84
85
|
def correct_validate_type(corrector, node)
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop identifies places where manually constructed SQL
|
7
|
+
# in `where` can be replaced with `where(attribute: value)`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# User.where('name = ?', 'Gabe')
|
12
|
+
# User.where('name = :name', name: 'Gabe')
|
13
|
+
# User.where('name IS NULL')
|
14
|
+
# User.where('name IN (?)', ['john', 'jane'])
|
15
|
+
# User.where('name IN (:names)', names: ['john', 'jane'])
|
16
|
+
# User.where('users.name = :name', name: 'Gabe')
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# User.where(name: 'Gabe')
|
20
|
+
# User.where(name: nil)
|
21
|
+
# User.where(name: ['john', 'jane'])
|
22
|
+
# User.where(users: { name: 'Gabe' })
|
23
|
+
class WhereEquals < Base
|
24
|
+
include RangeHelp
|
25
|
+
extend AutoCorrector
|
26
|
+
|
27
|
+
MSG = 'Use `%<good_method>s` instead of manually constructing SQL.'
|
28
|
+
RESTRICT_ON_SEND = %i[where].freeze
|
29
|
+
|
30
|
+
def_node_matcher :where_method_call?, <<~PATTERN
|
31
|
+
{
|
32
|
+
(send _ :where (array $str_type? $_ ?))
|
33
|
+
(send _ :where $str_type? $_ ?)
|
34
|
+
}
|
35
|
+
PATTERN
|
36
|
+
|
37
|
+
def on_send(node)
|
38
|
+
where_method_call?(node) do |template_node, value_node|
|
39
|
+
value_node = value_node.first
|
40
|
+
|
41
|
+
range = offense_range(node)
|
42
|
+
|
43
|
+
column_and_value = extract_column_and_value(template_node, value_node)
|
44
|
+
return unless column_and_value
|
45
|
+
|
46
|
+
good_method = build_good_method(*column_and_value)
|
47
|
+
message = format(MSG, good_method: good_method)
|
48
|
+
|
49
|
+
add_offense(range, message: message) do |corrector|
|
50
|
+
corrector.replace(range, good_method)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
EQ_ANONYMOUS_RE = /\A([\w.]+)\s+=\s+\?\z/.freeze # column = ?
|
56
|
+
IN_ANONYMOUS_RE = /\A([\w.]+)\s+IN\s+\(\?\)\z/i.freeze # column IN (?)
|
57
|
+
EQ_NAMED_RE = /\A([\w.]+)\s+=\s+:(\w+)\z/.freeze # column = :column
|
58
|
+
IN_NAMED_RE = /\A([\w.]+)\s+IN\s+\(:(\w+)\)\z/i.freeze # column IN (:column)
|
59
|
+
IS_NULL_RE = /\A([\w.]+)\s+IS\s+NULL\z/i.freeze # column IS NULL
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def offense_range(node)
|
64
|
+
range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
|
65
|
+
end
|
66
|
+
|
67
|
+
def extract_column_and_value(template_node, value_node)
|
68
|
+
value =
|
69
|
+
case template_node.value
|
70
|
+
when EQ_ANONYMOUS_RE, IN_ANONYMOUS_RE
|
71
|
+
value_node.source
|
72
|
+
when EQ_NAMED_RE, IN_NAMED_RE
|
73
|
+
return unless value_node&.hash_type?
|
74
|
+
|
75
|
+
pair = value_node.pairs.find { |p| p.key.value.to_sym == Regexp.last_match(2).to_sym }
|
76
|
+
pair.value.source
|
77
|
+
when IS_NULL_RE
|
78
|
+
'nil'
|
79
|
+
else
|
80
|
+
return
|
81
|
+
end
|
82
|
+
|
83
|
+
[Regexp.last_match(1), value]
|
84
|
+
end
|
85
|
+
|
86
|
+
def build_good_method(column, value)
|
87
|
+
if column.include?('.')
|
88
|
+
table, column = column.split('.')
|
89
|
+
|
90
|
+
"where(#{table}: { #{column}: #{value} })"
|
91
|
+
else
|
92
|
+
"where(#{column}: #{value})"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -3,9 +3,26 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
-
# This cop enforces
|
6
|
+
# This cop enforces consistent style when using `exists?`.
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# Two styles are supported for this cop. When EnforcedStyle is 'exists'
|
9
|
+
# then the cop enforces `exists?(...)` over `where(...).exists?`.
|
10
|
+
#
|
11
|
+
# When EnforcedStyle is 'where' then the cop enforces
|
12
|
+
# `where(...).exists?` over `exists?(...)`.
|
13
|
+
#
|
14
|
+
# This cop is unsafe for auto-correction because the behavior may change on the following case:
|
15
|
+
#
|
16
|
+
# [source,ruby]
|
17
|
+
# ----
|
18
|
+
# Author.includes(:articles).where(articles: {id: id}).exists?
|
19
|
+
# #=> Perform `eager_load` behavior (`LEFT JOIN` query) and get result.
|
20
|
+
#
|
21
|
+
# Author.includes(:articles).exists?(articles: {id: id})
|
22
|
+
# #=> Perform `preload` behavior and `ActiveRecord::StatementInvalid` error occurs.
|
23
|
+
# ----
|
24
|
+
#
|
25
|
+
# @example EnforcedStyle: exists (default)
|
9
26
|
# # bad
|
10
27
|
# User.where(name: 'john').exists?
|
11
28
|
# User.where(['name = ?', 'john']).exists?
|
@@ -17,51 +34,103 @@ module RuboCop
|
|
17
34
|
# User.where('length(name) > 10').exists?
|
18
35
|
# user.posts.exists?(published: true)
|
19
36
|
#
|
20
|
-
|
37
|
+
# @example EnforcedStyle: where
|
38
|
+
# # bad
|
39
|
+
# User.exists?(name: 'john')
|
40
|
+
# User.exists?(['name = ?', 'john'])
|
41
|
+
# User.exists?('name = ?', 'john')
|
42
|
+
# user.posts.exists?(published: true)
|
43
|
+
#
|
44
|
+
# # good
|
45
|
+
# User.where(name: 'john').exists?
|
46
|
+
# User.where(['name = ?', 'john']).exists?
|
47
|
+
# User.where('name = ?', 'john').exists?
|
48
|
+
# user.posts.where(published: true).exists?
|
49
|
+
# User.where('length(name) > 10').exists?
|
50
|
+
class WhereExists < Base
|
51
|
+
include ConfigurableEnforcedStyle
|
52
|
+
extend AutoCorrector
|
53
|
+
|
21
54
|
MSG = 'Prefer `%<good_method>s` over `%<bad_method>s`.'
|
55
|
+
RESTRICT_ON_SEND = %i[exists?].freeze
|
22
56
|
|
23
57
|
def_node_matcher :where_exists_call?, <<~PATTERN
|
24
58
|
(send (send _ :where $...) :exists?)
|
25
59
|
PATTERN
|
26
60
|
|
61
|
+
def_node_matcher :exists_with_args?, <<~PATTERN
|
62
|
+
(send _ :exists? $...)
|
63
|
+
PATTERN
|
64
|
+
|
27
65
|
def on_send(node)
|
28
|
-
|
66
|
+
find_offenses(node) do |args|
|
29
67
|
return unless convertable_args?(args)
|
30
68
|
|
31
69
|
range = correction_range(node)
|
32
|
-
|
33
|
-
|
70
|
+
good_method = build_good_method(args)
|
71
|
+
message = format(MSG, good_method: good_method, bad_method: range.source)
|
72
|
+
|
73
|
+
add_offense(range, message: message) do |corrector|
|
74
|
+
corrector.replace(range, good_method)
|
75
|
+
end
|
34
76
|
end
|
35
77
|
end
|
36
78
|
|
37
|
-
|
38
|
-
args = where_exists_call?(node)
|
79
|
+
private
|
39
80
|
|
40
|
-
|
41
|
-
|
42
|
-
correction_range(node),
|
43
|
-
build_good_method(args)
|
44
|
-
)
|
45
|
-
end
|
81
|
+
def where_style?
|
82
|
+
style == :where
|
46
83
|
end
|
47
84
|
|
48
|
-
|
85
|
+
def exists_style?
|
86
|
+
style == :exists
|
87
|
+
end
|
88
|
+
|
89
|
+
def find_offenses(node, &block)
|
90
|
+
if exists_style?
|
91
|
+
where_exists_call?(node, &block)
|
92
|
+
elsif where_style?
|
93
|
+
exists_with_args?(node, &block)
|
94
|
+
end
|
95
|
+
end
|
49
96
|
|
50
97
|
def convertable_args?(args)
|
98
|
+
return false if args.empty?
|
99
|
+
|
51
100
|
args.size > 1 || args[0].hash_type? || args[0].array_type?
|
52
101
|
end
|
53
102
|
|
54
103
|
def correction_range(node)
|
55
|
-
|
104
|
+
if exists_style?
|
105
|
+
node.receiver.loc.selector.join(node.loc.selector)
|
106
|
+
elsif where_style?
|
107
|
+
node.loc.selector.with(end_pos: node.loc.expression.end_pos)
|
108
|
+
end
|
56
109
|
end
|
57
110
|
|
58
111
|
def build_good_method(args)
|
112
|
+
if exists_style?
|
113
|
+
build_good_method_exists(args)
|
114
|
+
elsif where_style?
|
115
|
+
build_good_method_where(args)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def build_good_method_exists(args)
|
59
120
|
if args.size > 1
|
60
121
|
"exists?([#{args.map(&:source).join(', ')}])"
|
61
122
|
else
|
62
123
|
"exists?(#{args[0].source})"
|
63
124
|
end
|
64
125
|
end
|
126
|
+
|
127
|
+
def build_good_method_where(args)
|
128
|
+
if args.size > 1
|
129
|
+
"where(#{args.map(&:source).join(', ')}).exists?"
|
130
|
+
else
|
131
|
+
"where(#{args[0].source}).exists?"
|
132
|
+
end
|
133
|
+
end
|
65
134
|
end
|
66
135
|
end
|
67
136
|
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop identifies places where manually constructed SQL
|
7
|
+
# in `where` can be replaced with `where.not(...)`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# User.where('name != ?', 'Gabe')
|
12
|
+
# User.where('name != :name', name: 'Gabe')
|
13
|
+
# User.where('name <> ?', 'Gabe')
|
14
|
+
# User.where('name <> :name', name: 'Gabe')
|
15
|
+
# User.where('name IS NOT NULL')
|
16
|
+
# User.where('name NOT IN (?)', ['john', 'jane'])
|
17
|
+
# User.where('name NOT IN (:names)', names: ['john', 'jane'])
|
18
|
+
# User.where('users.name != :name', name: 'Gabe')
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# User.where.not(name: 'Gabe')
|
22
|
+
# User.where.not(name: nil)
|
23
|
+
# User.where.not(name: ['john', 'jane'])
|
24
|
+
# User.where.not(users: { name: 'Gabe' })
|
25
|
+
#
|
26
|
+
class WhereNot < Base
|
27
|
+
include RangeHelp
|
28
|
+
extend AutoCorrector
|
29
|
+
|
30
|
+
MSG = 'Use `%<good_method>s` instead of manually constructing negated SQL in `where`.'
|
31
|
+
RESTRICT_ON_SEND = %i[where].freeze
|
32
|
+
|
33
|
+
def_node_matcher :where_method_call?, <<~PATTERN
|
34
|
+
{
|
35
|
+
(send _ :where (array $str_type? $_ ?))
|
36
|
+
(send _ :where $str_type? $_ ?)
|
37
|
+
}
|
38
|
+
PATTERN
|
39
|
+
|
40
|
+
def on_send(node)
|
41
|
+
where_method_call?(node) do |template_node, value_node|
|
42
|
+
value_node = value_node.first
|
43
|
+
|
44
|
+
range = offense_range(node)
|
45
|
+
|
46
|
+
column_and_value = extract_column_and_value(template_node, value_node)
|
47
|
+
return unless column_and_value
|
48
|
+
|
49
|
+
good_method = build_good_method(*column_and_value)
|
50
|
+
message = format(MSG, good_method: good_method)
|
51
|
+
|
52
|
+
add_offense(range, message: message) do |corrector|
|
53
|
+
corrector.replace(range, good_method)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
NOT_EQ_ANONYMOUS_RE = /\A([\w.]+)\s+(?:!=|<>)\s+\?\z/.freeze # column != ?, column <> ?
|
59
|
+
NOT_IN_ANONYMOUS_RE = /\A([\w.]+)\s+NOT\s+IN\s+\(\?\)\z/i.freeze # column NOT IN (?)
|
60
|
+
NOT_EQ_NAMED_RE = /\A([\w.]+)\s+(?:!=|<>)\s+:(\w+)\z/.freeze # column != :column, column <> :column
|
61
|
+
NOT_IN_NAMED_RE = /\A([\w.]+)\s+NOT\s+IN\s+\(:(\w+)\)\z/i.freeze # column NOT IN (:column)
|
62
|
+
IS_NOT_NULL_RE = /\A([\w.]+)\s+IS\s+NOT\s+NULL\z/i.freeze # column IS NOT NULL
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def offense_range(node)
|
67
|
+
range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
|
68
|
+
end
|
69
|
+
|
70
|
+
def extract_column_and_value(template_node, value_node)
|
71
|
+
value =
|
72
|
+
case template_node.value
|
73
|
+
when NOT_EQ_ANONYMOUS_RE, NOT_IN_ANONYMOUS_RE
|
74
|
+
value_node.source
|
75
|
+
when NOT_EQ_NAMED_RE, NOT_IN_NAMED_RE
|
76
|
+
return unless value_node.hash_type?
|
77
|
+
|
78
|
+
pair = value_node.pairs.find { |p| p.key.value.to_sym == Regexp.last_match(2).to_sym }
|
79
|
+
pair.value.source
|
80
|
+
when IS_NOT_NULL_RE
|
81
|
+
'nil'
|
82
|
+
else
|
83
|
+
return
|
84
|
+
end
|
85
|
+
|
86
|
+
[Regexp.last_match(1), value]
|
87
|
+
end
|
88
|
+
|
89
|
+
def build_good_method(column, value)
|
90
|
+
if column.include?('.')
|
91
|
+
table, column = column.split('.')
|
92
|
+
|
93
|
+
"where.not(#{table}: { #{column}: #{value} })"
|
94
|
+
else
|
95
|
+
"where.not(#{column}: #{value})"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'mixin/active_record_helper'
|
4
|
+
require_relative 'mixin/enforce_superclass'
|
4
5
|
require_relative 'mixin/index_method'
|
5
6
|
require_relative 'mixin/target_rails_version'
|
6
7
|
|
@@ -9,11 +10,14 @@ require_relative 'rails/active_record_aliases'
|
|
9
10
|
require_relative 'rails/active_record_callbacks_order'
|
10
11
|
require_relative 'rails/active_record_override'
|
11
12
|
require_relative 'rails/active_support_aliases'
|
13
|
+
require_relative 'rails/after_commit_override'
|
12
14
|
require_relative 'rails/application_controller'
|
13
15
|
require_relative 'rails/application_job'
|
14
16
|
require_relative 'rails/application_mailer'
|
15
17
|
require_relative 'rails/application_record'
|
18
|
+
require_relative 'rails/arel_star'
|
16
19
|
require_relative 'rails/assert_not'
|
20
|
+
require_relative 'rails/attribute_default_block_value'
|
17
21
|
require_relative 'rails/belongs_to'
|
18
22
|
require_relative 'rails/blank'
|
19
23
|
require_relative 'rails/bulk_change_table'
|
@@ -27,6 +31,7 @@ require_relative 'rails/dynamic_find_by'
|
|
27
31
|
require_relative 'rails/enum_hash'
|
28
32
|
require_relative 'rails/enum_uniqueness'
|
29
33
|
require_relative 'rails/environment_comparison'
|
34
|
+
require_relative 'rails/environment_variable_access'
|
30
35
|
require_relative 'rails/exit'
|
31
36
|
require_relative 'rails/file_path'
|
32
37
|
require_relative 'rails/find_by'
|
@@ -48,6 +53,7 @@ require_relative 'rails/mailer_name'
|
|
48
53
|
require_relative 'rails/match_route'
|
49
54
|
require_relative 'rails/negate_include'
|
50
55
|
require_relative 'rails/not_null_column'
|
56
|
+
require_relative 'rails/order_by_id'
|
51
57
|
require_relative 'rails/output'
|
52
58
|
require_relative 'rails/output_safety'
|
53
59
|
require_relative 'rails/pick'
|
@@ -68,16 +74,22 @@ require_relative 'rails/relative_date_constant'
|
|
68
74
|
require_relative 'rails/render_inline'
|
69
75
|
require_relative 'rails/render_plain_text'
|
70
76
|
require_relative 'rails/request_referer'
|
77
|
+
require_relative 'rails/require_dependency'
|
71
78
|
require_relative 'rails/reversible_migration'
|
79
|
+
require_relative 'rails/reversible_migration_method_definition'
|
72
80
|
require_relative 'rails/safe_navigation'
|
73
81
|
require_relative 'rails/safe_navigation_with_blank'
|
74
82
|
require_relative 'rails/save_bang'
|
75
83
|
require_relative 'rails/scope_args'
|
76
84
|
require_relative 'rails/short_i18n'
|
77
85
|
require_relative 'rails/skips_model_validations'
|
86
|
+
require_relative 'rails/squished_sql_heredocs'
|
78
87
|
require_relative 'rails/time_zone'
|
88
|
+
require_relative 'rails/time_zone_assignment'
|
79
89
|
require_relative 'rails/uniq_before_pluck'
|
80
90
|
require_relative 'rails/unique_validation_without_index'
|
81
91
|
require_relative 'rails/unknown_env'
|
82
92
|
require_relative 'rails/validation'
|
93
|
+
require_relative 'rails/where_equals'
|
83
94
|
require_relative 'rails/where_exists'
|
95
|
+
require_relative 'rails/where_not'
|