rubocop-rails 2.7.1 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +18 -2
  4. data/config/default.yml +144 -6
  5. data/config/obsoletion.yml +7 -0
  6. data/lib/rubocop/cop/mixin/active_record_helper.rb +16 -3
  7. data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
  8. data/lib/rubocop/cop/mixin/index_method.rb +25 -11
  9. data/lib/rubocop/cop/rails/action_filter.rb +10 -14
  10. data/lib/rubocop/cop/rails/active_record_aliases.rb +13 -17
  11. data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +19 -16
  12. data/lib/rubocop/cop/rails/active_record_override.rb +1 -1
  13. data/lib/rubocop/cop/rails/active_support_aliases.rb +12 -21
  14. data/lib/rubocop/cop/rails/after_commit_override.rb +91 -0
  15. data/lib/rubocop/cop/rails/application_controller.rb +3 -7
  16. data/lib/rubocop/cop/rails/application_job.rb +2 -1
  17. data/lib/rubocop/cop/rails/application_mailer.rb +2 -7
  18. data/lib/rubocop/cop/rails/application_record.rb +2 -7
  19. data/lib/rubocop/cop/rails/arel_star.rb +41 -0
  20. data/lib/rubocop/cop/rails/assert_not.rb +8 -10
  21. data/lib/rubocop/cop/rails/attribute_default_block_value.rb +90 -0
  22. data/lib/rubocop/cop/rails/belongs_to.rb +10 -19
  23. data/lib/rubocop/cop/rails/blank.rb +31 -27
  24. data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
  25. data/lib/rubocop/cop/rails/content_tag.rb +34 -19
  26. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -1
  27. data/lib/rubocop/cop/rails/date.rb +10 -11
  28. data/lib/rubocop/cop/rails/default_scope.rb +11 -4
  29. data/lib/rubocop/cop/rails/delegate.rb +9 -9
  30. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
  31. data/lib/rubocop/cop/rails/dynamic_find_by.rb +15 -12
  32. data/lib/rubocop/cop/rails/enum_hash.rb +11 -10
  33. data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -1
  34. data/lib/rubocop/cop/rails/environment_comparison.rb +18 -14
  35. data/lib/rubocop/cop/rails/environment_variable_access.rb +67 -0
  36. data/lib/rubocop/cop/rails/exit.rb +4 -10
  37. data/lib/rubocop/cop/rails/file_path.rb +7 -8
  38. data/lib/rubocop/cop/rails/find_by.rb +13 -13
  39. data/lib/rubocop/cop/rails/find_by_id.rb +12 -21
  40. data/lib/rubocop/cop/rails/find_each.rb +19 -18
  41. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
  42. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +37 -10
  43. data/lib/rubocop/cop/rails/helper_instance_variable.rb +30 -2
  44. data/lib/rubocop/cop/rails/http_positional_arguments.rb +32 -21
  45. data/lib/rubocop/cop/rails/http_status.rb +7 -9
  46. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +8 -6
  47. data/lib/rubocop/cop/rails/index_by.rb +11 -2
  48. data/lib/rubocop/cop/rails/index_with.rb +11 -2
  49. data/lib/rubocop/cop/rails/inquiry.rb +7 -2
  50. data/lib/rubocop/cop/rails/inverse_of.rb +3 -2
  51. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -15
  52. data/lib/rubocop/cop/rails/link_to_blank.rb +25 -23
  53. data/lib/rubocop/cop/rails/mailer_name.rb +19 -13
  54. data/lib/rubocop/cop/rails/match_route.rb +14 -13
  55. data/lib/rubocop/cop/rails/negate_include.rb +10 -8
  56. data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
  57. data/lib/rubocop/cop/rails/order_by_id.rb +52 -0
  58. data/lib/rubocop/cop/rails/output.rb +5 -2
  59. data/lib/rubocop/cop/rails/output_safety.rb +3 -2
  60. data/lib/rubocop/cop/rails/pick.rb +14 -12
  61. data/lib/rubocop/cop/rails/pluck.rb +6 -9
  62. data/lib/rubocop/cop/rails/pluck_id.rb +4 -6
  63. data/lib/rubocop/cop/rails/pluck_in_where.rb +39 -5
  64. data/lib/rubocop/cop/rails/pluralization_grammar.rb +10 -14
  65. data/lib/rubocop/cop/rails/presence.rb +12 -13
  66. data/lib/rubocop/cop/rails/present.rb +30 -24
  67. data/lib/rubocop/cop/rails/rake_environment.rb +8 -10
  68. data/lib/rubocop/cop/rails/read_write_attribute.rb +12 -11
  69. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +29 -31
  70. data/lib/rubocop/cop/rails/redundant_foreign_key.rb +9 -12
  71. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +11 -10
  72. data/lib/rubocop/cop/rails/reflection_class_name.rb +18 -4
  73. data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
  74. data/lib/rubocop/cop/rails/relative_date_constant.rb +34 -22
  75. data/lib/rubocop/cop/rails/render_inline.rb +2 -1
  76. data/lib/rubocop/cop/rails/render_plain_text.rb +9 -14
  77. data/lib/rubocop/cop/rails/request_referer.rb +7 -7
  78. data/lib/rubocop/cop/rails/require_dependency.rb +38 -0
  79. data/lib/rubocop/cop/rails/reversible_migration.rb +83 -8
  80. data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +75 -0
  81. data/lib/rubocop/cop/rails/safe_navigation.rb +30 -11
  82. data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
  83. data/lib/rubocop/cop/rails/save_bang.rb +19 -22
  84. data/lib/rubocop/cop/rails/scope_args.rb +2 -1
  85. data/lib/rubocop/cop/rails/short_i18n.rb +7 -9
  86. data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -4
  87. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +82 -0
  88. data/lib/rubocop/cop/rails/time_zone.rb +35 -25
  89. data/lib/rubocop/cop/rails/time_zone_assignment.rb +37 -0
  90. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +6 -6
  91. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +18 -8
  92. data/lib/rubocop/cop/rails/unknown_env.rb +3 -3
  93. data/lib/rubocop/cop/rails/validation.rb +15 -14
  94. data/lib/rubocop/cop/rails/where_equals.rb +98 -0
  95. data/lib/rubocop/cop/rails/where_exists.rb +85 -16
  96. data/lib/rubocop/cop/rails/where_not.rb +101 -0
  97. data/lib/rubocop/cop/rails_cops.rb +12 -0
  98. data/lib/rubocop/rails.rb +2 -0
  99. data/lib/rubocop/rails/schema_loader.rb +4 -4
  100. data/lib/rubocop/rails/schema_loader/schema.rb +4 -8
  101. data/lib/rubocop/rails/version.rb +5 -1
  102. 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 < Cop
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
- DENYLIST = TYPES.map { |p| "validates_#{p}_of".to_sym }.freeze
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 unless !node.receiver && DENYLIST.include?(node.method_name)
59
+ return if node.receiver
58
60
 
59
- add_offense(node, location: :selector)
60
- end
61
+ range = node.loc.selector
61
62
 
62
- def autocorrect(node)
63
- last_argument = node.arguments.last
64
- return if !last_argument.literal? && !last_argument.splat_type? &&
65
- !frozen_array_argument?(last_argument)
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
- lambda do |corrector|
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
- format(MSG, prefer: preferred_method(node.method_name),
77
- current: node.method_name)
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[DENYLIST.index(method.to_sym)]
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 the use of `exists?(...)` over `where(...).exists?`.
6
+ # This cop enforces consistent style when using `exists?`.
7
7
  #
8
- # @example
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
- class WhereExists < Cop
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
- where_exists_call?(node) do |args|
66
+ find_offenses(node) do |args|
29
67
  return unless convertable_args?(args)
30
68
 
31
69
  range = correction_range(node)
32
- message = format(MSG, good_method: build_good_method(args), bad_method: range.source)
33
- add_offense(node, location: range, message: message)
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
- def autocorrect(node)
38
- args = where_exists_call?(node)
79
+ private
39
80
 
40
- lambda do |corrector|
41
- corrector.replace(
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
- private
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
- node.receiver.loc.selector.join(node.loc.selector)
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'