sevencop 0.20.1 → 0.22.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/Gemfile.lock +13 -1
  4. data/README.md +19 -4
  5. data/config/default.yml +163 -0
  6. data/lib/rubocop/cop/sevencop/factory_bot_association_option.rb +89 -0
  7. data/lib/rubocop/cop/sevencop/factory_bot_association_style.rb +167 -0
  8. data/lib/rubocop/cop/sevencop/rails_inferred_spec_type.rb +1 -1
  9. data/lib/rubocop/cop/sevencop/rails_migration_add_check_constraint.rb +111 -0
  10. data/lib/rubocop/cop/sevencop/rails_migration_add_column_with_default_value.rb +229 -0
  11. data/lib/rubocop/cop/sevencop/rails_migration_add_foreign_key.rb +166 -0
  12. data/lib/rubocop/cop/sevencop/rails_migration_add_index_concurrently.rb +164 -0
  13. data/lib/rubocop/cop/sevencop/rails_migration_batch_in_batches.rb +95 -0
  14. data/lib/rubocop/cop/sevencop/rails_migration_batch_in_transaction.rb +83 -0
  15. data/lib/rubocop/cop/sevencop/rails_migration_batch_with_throttling.rb +108 -0
  16. data/lib/rubocop/cop/sevencop/rails_migration_change_column.rb +113 -0
  17. data/lib/rubocop/cop/sevencop/rails_migration_change_column_null.rb +128 -0
  18. data/lib/rubocop/cop/sevencop/rails_migration_create_table_force.rb +89 -0
  19. data/lib/rubocop/cop/sevencop/rails_migration_jsonb.rb +131 -0
  20. data/lib/rubocop/cop/sevencop/rails_migration_remove_column.rb +258 -0
  21. data/lib/rubocop/cop/sevencop/rails_migration_rename_column.rb +81 -0
  22. data/lib/rubocop/cop/sevencop/rails_migration_rename_table.rb +79 -0
  23. data/lib/rubocop/cop/sevencop/rails_migration_reserved_word_mysql.rb +2 -19
  24. data/lib/rubocop/cop/sevencop/rails_migration_unique_index_columns_count.rb +92 -0
  25. data/lib/sevencop/config_loader.rb +11 -10
  26. data/lib/sevencop/cop_concerns/batch_processing.rb +32 -0
  27. data/lib/sevencop/cop_concerns/column_type_method.rb +26 -0
  28. data/lib/sevencop/cop_concerns/disable_ddl_transaction.rb +49 -0
  29. data/lib/sevencop/cop_concerns.rb +3 -0
  30. data/lib/sevencop/rubocop_extension.rb +6 -1
  31. data/lib/sevencop/version.rb +1 -1
  32. data/lib/sevencop.rb +17 -0
  33. data/sevencop.gemspec +1 -0
  34. metadata +36 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22e21f2ba7c484fc1fd0d23b9b7d4dcf70d3e0f2f5f764e95e6dc65d10c419e9
4
- data.tar.gz: b689a364af2f7728c3947575d4edcc5f79a9ce3767fa769acf4829587fa9e63c
3
+ metadata.gz: e2aff4e0e776ef3fa5b3f71ece7b7c83013caadaf829fc86827ab246f5f80382
4
+ data.tar.gz: 1889785ce282e4d530c7eef4a54afaa948181b1557e788425e9b30e831935b77
5
5
  SHA512:
6
- metadata.gz: 9cab7cab01a11e6c9ea1de15a97ae4ea6c8315dc4c4a2304d4ee1178775dd8526cccd2a42cdca9d30069936e816bde32cd58451e157fa85b737bb2bfa5368465
7
- data.tar.gz: 0040a81647501bcb03ee0f0bd0f97722b2483c202751debc7a530d58677a4d822e73039803a6066d1d6085e2dcd7c9a06fead8c06991e2b14afdc927ebd8b07b
6
+ metadata.gz: 386a275378516b205cbd1dc4d50226776d106dc98eb8c534973ff7379c39b59f0e49ae4985058f79254d2256a09ac459b6357e1c5d0f03a8e2d780ec8b1fc990
7
+ data.tar.gz: 91adea811d280655577fd88cdb4b861b3a9e04f4c89d9542a4ce38281f325cfe0be590cb45ce8937375b4d13e67970518e6381531f46087689e58f3b8d0c5156
data/.rubocop.yml CHANGED
@@ -13,6 +13,9 @@ AllCops:
13
13
  Gemspec/RequireMFA:
14
14
  Enabled: false
15
15
 
16
+ Layout/LineLength:
17
+ Enabled: false
18
+
16
19
  Metrics:
17
20
  Enabled: false
18
21
 
@@ -49,6 +52,9 @@ Sevencop/MethodDefinitionKeywordArgumentOrdered:
49
52
  Sevencop/MethodDefinitionOrdered:
50
53
  Enabled: true
51
54
 
55
+ Sevencop/RequireOrdered:
56
+ Enabled: true
57
+
52
58
  Style/Documentation:
53
59
  Enabled: false
54
60
 
data/Gemfile.lock CHANGED
@@ -1,15 +1,25 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sevencop (0.20.1)
4
+ sevencop (0.22.0)
5
+ activesupport
5
6
  rubocop
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
9
10
  specs:
11
+ activesupport (7.0.4)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (>= 1.6, < 2)
14
+ minitest (>= 5.1)
15
+ tzinfo (~> 2.0)
10
16
  ast (2.4.2)
17
+ concurrent-ruby (1.1.10)
11
18
  diff-lcs (1.5.0)
19
+ i18n (1.12.0)
20
+ concurrent-ruby (~> 1.0)
12
21
  json (2.6.2)
22
+ minitest (5.16.3)
13
23
  parallel (1.22.1)
14
24
  parser (3.1.2.1)
15
25
  ast (~> 2.4.1)
@@ -50,6 +60,8 @@ GEM
50
60
  rubocop-rspec (2.13.1)
51
61
  rubocop (~> 1.33)
52
62
  ruby-progressbar (1.11.0)
63
+ tzinfo (2.0.5)
64
+ concurrent-ruby (~> 1.0)
53
65
  unicode-display_width (2.3.0)
54
66
 
55
67
  PLATFORMS
data/README.md CHANGED
@@ -24,11 +24,13 @@ Sevencop/MethodDefinitionOrdered:
24
24
  Enabled: true
25
25
  ```
26
26
 
27
- ## Cops
27
+ Note that all cops are `Enabled: false` by default.
28
28
 
29
- Choose the cops you want to use and enable them on your .rubocop.yml.
29
+ ## Cops
30
30
 
31
31
  - [Sevencop/AutoloadOrdered](lib/rubocop/cop/sevencop/autoload_ordered.rb)
32
+ - [Sevencop/FactoryBotAssociationOption](lib/rubocop/cop/sevencop/factory_bot_association_option.rb)
33
+ - [Sevencop/FactoryBotAssociationStyle](lib/rubocop/cop/sevencop/factory_bot_association_style.rb)
32
34
  - [Sevencop/HashElementOrdered](lib/rubocop/cop/sevencop/hash_element_ordered.rb)
33
35
  - [Sevencop/MethodDefinitionArgumentsMultiline](lib/rubocop/cop/sevencop/method_definition_arguments_multiline.rb)
34
36
  - [Sevencop/MethodDefinitionInIncluded](lib/rubocop/cop/sevencop/method_definition_in_included.rb)
@@ -36,12 +38,25 @@ Choose the cops you want to use and enable them on your .rubocop.yml.
36
38
  - [Sevencop/MethodDefinitionOrdered](lib/rubocop/cop/sevencop/method_definition_ordered.rb)
37
39
  - [Sevencop/RailsBelongsToOptional](lib/rubocop/cop/sevencop/rails_belongs_to_optional.rb)
38
40
  - [Sevencop/RailsInferredSpecType](lib/rubocop/cop/sevencop/rails_inferred_spec_type.rb)
41
+ - [Sevencop/RailsMigrationAddCheckConstraint](lib/rubocop/cop/sevencop/rails_migration_add_check_constraint.rb)
42
+ - [Sevencop/RailsMigrationAddColumnWithDefaultValue](lib/rubocop/cop/sevencop/rails_migration_add_column_with_default_value.rb)
43
+ - [Sevencop/RailsMigrationAddForeignKey](lib/rubocop/cop/sevencop/rails_migration_add_foreign_key.rb)
44
+ - [Sevencop/RailsMigrationAddIndexConcurrently](lib/rubocop/cop/sevencop/rails_migration_add_index_concurrently.rb)
45
+ - [Sevencop/RailsMigrationBatchInBatches](lib/rubocop/cop/sevencop/rails_migration_batch_in_batches.rb)
46
+ - [Sevencop/RailsMigrationBatchInTransaction](lib/rubocop/cop/sevencop/rails_migration_batch_in_transaction.rb)
47
+ - [Sevencop/RailsMigrationBatchWithThrottling](lib/rubocop/cop/sevencop/rails_migration_batch_with_throttling.rb)
48
+ - [Sevencop/RailsMigrationChangeColumn](lib/rubocop/cop/sevencop/rails_migration_change_column.rb)
49
+ - [Sevencop/RailsMigrationChangeColumnNull](lib/rubocop/cop/sevencop/rails_migration_change_column_null.rb)
50
+ - [Sevencop/RailsMigrationCreateTableForce](lib/rubocop/cop/sevencop/rails_migration_create_table_force.rb)
51
+ - [Sevencop/RailsMigrationJsonb](lib/rubocop/cop/sevencop/rails_migration_jsonb.rb)
52
+ - [Sevencop/RailsMigrationRemoveColumn](lib/rubocop/cop/sevencop/rails_migration_remove_column.rb)
53
+ - [Sevencop/RailsMigrationRenameColumn](lib/rubocop/cop/sevencop/rails_migration_rename_column.rb)
54
+ - [Sevencop/RailsMigrationRenameTable](lib/rubocop/cop/sevencop/rails_migration_rename_table.rb)
39
55
  - [Sevencop/RailsMigrationReservedWordMysql](lib/rubocop/cop/sevencop/rails_migration_reserved_word_mysql.rb)
56
+ - [Sevencop/RailsMigrationUniqueIndexColumnsCount](lib/rubocop/cop/sevencop/rails_migration_unique_index_columns_count.rb)
40
57
  - [Sevencop/RailsOrderField](lib/rubocop/cop/sevencop/rails_order_field.rb)
41
58
  - [Sevencop/RailsUniquenessValidatorExplicitCaseSensitivity](lib/rubocop/cop/sevencop/rails_uniqueness_validator_explicit_case_sensitivity.rb)
42
59
  - [Sevencop/RailsWhereNot](lib/rubocop/cop/sevencop/rails_where_not.rb)
43
60
  - [Sevencop/RequireOrdered](lib/rubocop/cop/sevencop/require_ordered.rb)
44
61
  - [Sevencop/RSpecDescribeHttpEndpoint](lib/rubocop/cop/sevencop/rspec_describe_http_endpoint.rb)
45
62
  - [Sevencop/RSpecExamplesInSameGroup](lib/rubocop/cop/sevencop/rspec_examples_in_same_group.rb)
46
-
47
- Note that all cops are `Enabled: false` by default.
data/config/default.yml CHANGED
@@ -5,6 +5,35 @@ Sevencop/AutoloadOrdered:
5
5
  Safe: false
6
6
  VersionAdded: '0.12'
7
7
 
8
+ Sevencop/FactoryBotAssociationOptions:
9
+ Description: |
10
+ Remove redundant options from FactoryBot associations.
11
+ Enabled: false
12
+ VersionAdded: '0.21'
13
+
14
+ Sevencop/FactoryBotAssociationStyle:
15
+ Description: |
16
+ Use consistent style in FactoryBot associations.
17
+ Enabled: false
18
+ Safe: false
19
+ VersionAdded: '0.21'
20
+ EnforcedStyle: implicit
21
+ SupportedStyles:
22
+ - explicit
23
+ - implicit
24
+ inherit_mode:
25
+ merge:
26
+ - NonImplicitAssociationMethodNames
27
+ NonImplicitAssociationMethodNames:
28
+ - skip_create
29
+ Include:
30
+ - factories.rb
31
+ - factories/*.rb
32
+ - spec/factories.rb
33
+ - spec/factories/*.rb
34
+ - test/factories.rb
35
+ - test/factories/*.rb
36
+
8
37
  Sevencop/HashElementOrdered:
9
38
  Description: |
10
39
  Sort Hash elements by key.
@@ -53,6 +82,131 @@ Sevencop/RailsInferredSpecType:
53
82
  Safe: false
54
83
  VersionAdded: '0.9'
55
84
 
85
+ Sevencop/RailsMigrationAddCheckConstraint:
86
+ Description: |
87
+ Activate a check constraint in a separate migration in PostgreSQL.
88
+ Enabled: false
89
+ Safe: false
90
+ VersionAdded: '0.22'
91
+ Include:
92
+ - db/migrate/**/*.rb
93
+
94
+ Sevencop/RailsMigrationAddColumnWithDefaultValue:
95
+ Description: |
96
+ Add the column without a default value then change the default.
97
+ Enabled: false
98
+ Safe: false
99
+ VersionAdded: '0.22'
100
+ Include:
101
+ - db/migrate/**/*.rb
102
+
103
+ Sevencop/RailsMigrationAddForeignKey:
104
+ Description: |
105
+ Activate a foreign key validation in a separate migration in PostgreSQL.
106
+ Enabled: false
107
+ Safe: false
108
+ VersionAdded: '0.22'
109
+ Include:
110
+ - db/migrate/**/*.rb
111
+
112
+ Sevencop/RailsMigrationAddIndexConcurrently:
113
+ Description: |
114
+ Use `algorithm: :concurrently` on adding indexes to existing tables in PostgreSQL.
115
+ Enabled: false
116
+ Safe: false
117
+ VersionAdded: '0.22'
118
+ Include:
119
+ - db/migrate/**/*.rb
120
+
121
+ Sevencop/RailsMigrationBatchInBatches:
122
+ Description: |
123
+ Use `in_batches` in batch processing.
124
+ Enabled: false
125
+ Safe: false
126
+ VersionAdded: '0.22'
127
+ Include:
128
+ - db/migrate/**/*.rb
129
+
130
+ Sevencop/RailsMigrationBatchInTransaction:
131
+ Description: |
132
+ Disable transaction in batch processing.
133
+ Enabled: false
134
+ Safe: false
135
+ VersionAdded: '0.22'
136
+ Include:
137
+ - db/migrate/**/*.rb
138
+
139
+ Sevencop/RailsMigrationBatchWithThrottling:
140
+ Description: |
141
+ Use throttling in batch processing.
142
+ Enabled: false
143
+ Safe: false
144
+ VersionAdded: '0.22'
145
+ Include:
146
+ - db/migrate/**/*.rb
147
+
148
+ Sevencop/RailsMigrationCreateTableForce:
149
+ Description: |
150
+ Create tables without `force: true` option.
151
+ Enabled: false
152
+ VersionAdded: '0.22'
153
+ Include:
154
+ - db/migrate/**/*.rb
155
+
156
+ Sevencop/RailsMigrationJsonb:
157
+ Description: |
158
+ Prefer `jsonb` to `json`.
159
+ Enabled: false
160
+ Safe: false
161
+ VersionAdded: '0.22'
162
+ Include:
163
+ - db/migrate/**/*.rb
164
+
165
+ Sevencop/RailsMigrationChangeColumn:
166
+ Description: |
167
+ Avoid changing column type that is in use.
168
+ Enabled: false
169
+ Safe: false
170
+ VersionAdded: '0.22'
171
+ Include:
172
+ - db/migrate/**/*.rb
173
+
174
+ Sevencop/RailsMigrationChangeColumnNull:
175
+ Description: |
176
+ Avoid simply setting `NOT NULL` constraint on an existing column in PostgreSQL.
177
+ Enabled: false
178
+ Safe: false
179
+ VersionAdded: '0.22'
180
+ Include:
181
+ - db/migrate/**/*.rb
182
+
183
+ Sevencop/RailsMigrationRemoveColumn:
184
+ Description: |
185
+ Add to `ignored_columns` and then remove the column.
186
+ Enabled: false
187
+ Safe: false
188
+ VersionAdded: '0.22'
189
+ Include:
190
+ - db/migrate/**/*.rb
191
+
192
+ Sevencop/RailsMigrationRenameColumn:
193
+ Description: |
194
+ Avoid renaming columns that are in use.
195
+ Enabled: false
196
+ Safe: false
197
+ VersionAdded: '0.22'
198
+ Include:
199
+ - db/migrate/**/*.rb
200
+
201
+ Sevencop/RailsMigrationRenameTable:
202
+ Description: |
203
+ Avoid removing tables that are in use.
204
+ Enabled: false
205
+ Safe: false
206
+ VersionAdded: '0.22'
207
+ Include:
208
+ - db/migrate/**/*.rb
209
+
56
210
  Sevencop/RailsMigrationReservedWordMysql:
57
211
  Description: |
58
212
  Avoid using MySQL reserved words as identifiers.
@@ -62,6 +216,15 @@ Sevencop/RailsMigrationReservedWordMysql:
62
216
  Include:
63
217
  - db/migrate/**/*.rb
64
218
 
219
+ Sevencop/RailsMigrationUniqueIndexColumnsCount:
220
+ Description: |
221
+ Keep unique index columns count less than a specified number.
222
+ Enabled: false
223
+ VersionAdded: '0.22'
224
+ MaxColumnsCount: 3
225
+ Include:
226
+ - db/migrate/**/*.rb
227
+
65
228
  Sevencop/RailsOrderField:
66
229
  Description: |
67
230
  Wrap safe SQL String by `Arel.sql`.
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Sevencop
6
+ # Remove redundant options from FactoryBot associations.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # association :user, factory: :user
11
+ #
12
+ # # good
13
+ # association :user
14
+ class FactoryBotAssociationOption < RuboCop::Cop::Base
15
+ extend AutoCorrector
16
+
17
+ include RangeHelp
18
+
19
+ MSG = 'Remove redundant options from FactoryBot associations.'
20
+
21
+ RESTRICT_ON_SEND = %i[association].freeze
22
+
23
+ # @param node [RuboCop::AST::SendNode]
24
+ # @return [void]
25
+ def on_send(node)
26
+ association_name = association_name_from(node)
27
+ factory_option = factory_option_from(node)
28
+ return if !factory_option || association_name != factory_option.value.value
29
+
30
+ add_offense(factory_option) do |corrector|
31
+ autocorrect(corrector, factory_option)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ # @!method association_name_from(node)
38
+ # @param node [RuboCop::AST::SendNode]
39
+ # @return [Symbol, nil]
40
+ def_node_matcher :association_name_from, <<~PATTERN
41
+ (send
42
+ nil?
43
+ _
44
+ (sym $_)
45
+ ...
46
+ )
47
+ PATTERN
48
+
49
+ # @!method factory_option_from(node)
50
+ # @param node [RuboCop::AST::SendNode]
51
+ # @return [RuboCop::AST::PairNode, nil]
52
+ def_node_matcher :factory_option_from, <<~PATTERN
53
+ (send
54
+ nil?
55
+ _
56
+ _
57
+ (hash
58
+ <
59
+ $(pair
60
+ (sym :factory)
61
+ sym
62
+ )
63
+ ...
64
+ >
65
+ )
66
+ )
67
+ PATTERN
68
+
69
+ # @param corrector [RuboCop::Cop::Corrector]
70
+ # @param node [RuboCop::AST::PairNode]
71
+ # @return [void]
72
+ def autocorrect(
73
+ corrector,
74
+ node
75
+ )
76
+ corrector.remove(
77
+ range_with_surrounding_comma(
78
+ range_with_surrounding_space(
79
+ node.location.expression,
80
+ side: :left
81
+ ),
82
+ :left
83
+ )
84
+ )
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Sevencop
6
+ # Use consistent style in FactoryBot associations.
7
+ #
8
+ # @safety
9
+ # This cop may cause false-positives in `EnforcedStyle: explicit` case.
10
+ # It recognizes any method call that has no arguments as an implicit association
11
+ # but it might be a user-defined trait call.
12
+ #
13
+ # @example EnforcedStyle: implicit (default)
14
+ # # bad
15
+ # association :user
16
+ #
17
+ # # good
18
+ # user
19
+ #
20
+ # # good
21
+ # association :author, factory: user
22
+ #
23
+ # @example EnforcedStyle: explicit
24
+ # # bad
25
+ # user
26
+ #
27
+ # # good
28
+ # association :user
29
+ #
30
+ # # good (defined in NonImplicitAssociationMethodNames)
31
+ # skip_create
32
+ class FactoryBotAssociationStyle < RuboCop::Cop::Base
33
+ extend AutoCorrector
34
+
35
+ include ConfigurableEnforcedStyle
36
+
37
+ MSG = 'Use consistent style in FactoryBot associations.'
38
+
39
+ RESTRICT_ON_SEND = %i[factory].freeze
40
+
41
+ # @param node [RuboCop::AST::SendNode]
42
+ # @return [void]
43
+ def on_send(node)
44
+ bad_associations_in(node).each do |association|
45
+ add_offense(association) do |corrector|
46
+ autocorrect(corrector, association)
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ # @!method explicit_association?(node)
54
+ # @param node [RuboCop::AST::SendNode]
55
+ # @return [Boolean]
56
+ def_node_matcher :explicit_association?, <<~PATTERN
57
+ (send
58
+ nil?
59
+ :association
60
+ ...
61
+ )
62
+ PATTERN
63
+
64
+ # @!method implicit_association?(node)
65
+ # @param node [RuboCop::AST::SendNode]
66
+ # @return [Boolean]
67
+ def_node_matcher :implicit_association?, <<~PATTERN
68
+ (send
69
+ nil?
70
+ !#non_implicit_association_method_name?
71
+ )
72
+ PATTERN
73
+
74
+ # @param corrector [RuboCop::Cop::Corrector]
75
+ # @param node [RuboCop::AST::SendNode]
76
+ def autocorrect(
77
+ corrector,
78
+ node
79
+ )
80
+ case style
81
+ when :explicit
82
+ autocorrect_to_explicit_style(corrector, node)
83
+ when :implicit
84
+ autocorrect_to_implicit_style(corrector, node)
85
+ end
86
+ end
87
+
88
+ # @param corrector [RuboCop::Cop::Corrector]
89
+ # @param node [RuboCop::AST::SendNode]
90
+ # @return [void]
91
+ def autocorrect_to_explicit_style(
92
+ corrector,
93
+ node
94
+ )
95
+ corrector.replace(node, "association :#{node.method_name}")
96
+ end
97
+
98
+ # @param corrector [RuboCop::Cop::Corrector]
99
+ # @param node [RuboCop::AST::SendNode]
100
+ # @return [void]
101
+ def autocorrect_to_implicit_style(
102
+ corrector,
103
+ node
104
+ )
105
+ corrector.replace(node, node.first_argument.value.to_s)
106
+ end
107
+
108
+ # @param node [RuboCop::AST::SendNode]
109
+ # @return [Boolean]
110
+ def autocorrectable_to_implicit_style?(node)
111
+ node.arguments.one?
112
+ end
113
+
114
+ # @param node [RuboCop::AST::SendNode]
115
+ # @return [Boolean]
116
+ def bad?(node)
117
+ case style
118
+ when :explicit
119
+ bad_to_explicit_style?(node)
120
+ when :implicit
121
+ bad_to_implicit_style?(node)
122
+ end
123
+ end
124
+
125
+ # @param node [RuboCop::AST::SendNode]
126
+ # @return [Array<RuboCop::AST::SendNode>]
127
+ def bad_associations_in(node)
128
+ children_of_factory_block(node).select do |child|
129
+ bad?(child)
130
+ end
131
+ end
132
+
133
+ # @param node [RuboCop::AST::SendNode]
134
+ # @return [Boolean]
135
+ def bad_to_explicit_style?(node)
136
+ implicit_association?(node)
137
+ end
138
+
139
+ # @param node [RuboCop::AST::SendNode]
140
+ # @return [Boolean]
141
+ def bad_to_implicit_style?(node)
142
+ explicit_association?(node) && autocorrectable_to_implicit_style?(node)
143
+ end
144
+
145
+ # @param node [RuboCop::AST::SendNode]
146
+ # @return [Array<RuboCop::AST::Node>]
147
+ def children_of_factory_block(node)
148
+ block = node.parent
149
+ return [] unless block
150
+ return [] unless block.block_type?
151
+
152
+ if block.body.begin_type?
153
+ block.body.children
154
+ else
155
+ [block.body]
156
+ end
157
+ end
158
+
159
+ # @param method_name [Symbol]
160
+ # @return [Boolean]
161
+ def non_implicit_association_method_name?(method_name)
162
+ cop_config['NonImplicitAssociationMethodNames'].include?(method_name.to_s)
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -73,7 +73,7 @@ module RuboCop
73
73
  _*
74
74
  ({ hash | kwargs }
75
75
  (pair ...)*
76
- $(pair (sym :type) (sym _))
76
+ $(pair (sym :type) sym)
77
77
  (pair ...)*
78
78
  )
79
79
  )
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Sevencop
6
+ # Activate a check constraint in a separate migration in PostgreSQL.
7
+ #
8
+ # Adding a check constraint without `NOT VALID` blocks reads and writes in Postgres and
9
+ # blocks writes in MySQL and MariaDB while every row is checked.
10
+ #
11
+ # @safety
12
+ # Only meaningful in PostgreSQL.
13
+ #
14
+ # @example
15
+ # # bad
16
+ # class AddCheckConstraintToOrdersPrice < ActiveRecord::Migration[7.0]
17
+ # def change
18
+ # add_check_constraint :orders, 'price > 0', name: 'orders_price_positive'
19
+ # end
20
+ # end
21
+ #
22
+ # # good
23
+ # class AddCheckConstraintToOrdersPriceWithoutValidation < ActiveRecord::Migration[7.0]
24
+ # def change
25
+ # add_check_constraint :orders, 'price > 0', name: 'orders_price_positive', validate: false
26
+ # end
27
+ # end
28
+ #
29
+ # class ActivateCheckConstraintOnOrdersPrice < ActiveRecord::Migration[7.0]
30
+ # def change
31
+ # validate_check_constraint :orders, name: 'orders_price_positive'
32
+ # end
33
+ # end
34
+ class RailsMigrationAddCheckConstraint < RuboCop::Cop::Base
35
+ extend AutoCorrector
36
+
37
+ MSG = 'Activate a check constraint in a separate migration in PostgreSQL.'
38
+
39
+ RESTRICT_ON_SEND = %i[
40
+ add_check_constraint
41
+ ].freeze
42
+
43
+ # @param node [RuboCop::AST::SendNode]
44
+ # @return [void]
45
+ def on_send(node)
46
+ return unless bad?(node)
47
+
48
+ add_offense(node) do |corrector|
49
+ autocorrect(corrector, node)
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ # @!method add_check_constraint?(node)
56
+ # @param node [RuboCop::AST::SendNode]
57
+ # @return [Boolean]
58
+ def_node_matcher :add_check_constraint?, <<~PATTERN
59
+ (send
60
+ nil?
61
+ :add_check_constraint
62
+ ...
63
+ )
64
+ PATTERN
65
+
66
+ # @!method add_check_constraint_with_validate_false?(node)
67
+ # @param node [RuboCop::AST::SendNode]
68
+ # @return [Boolean]
69
+ def_node_matcher :add_check_constraint_with_validate_false?, <<~PATTERN
70
+ (send
71
+ nil?
72
+ :add_check_constraint
73
+ _
74
+ _
75
+ (hash
76
+ <
77
+ (pair
78
+ (sym :validate)
79
+ false
80
+ )
81
+ ...
82
+ >
83
+ )
84
+ )
85
+ PATTERN
86
+
87
+ # @param corrector [RuboCop::Cop::Corrector]
88
+ # @param node [RuboCop::AST::SendNode]
89
+ # @return [void]
90
+ def autocorrect(
91
+ corrector,
92
+ node
93
+ )
94
+ target = node.last_argument
95
+ target = target.pairs.last if target.hash_type?
96
+ corrector.insert_after(
97
+ target,
98
+ ', validate: false'
99
+ )
100
+ end
101
+
102
+ # @param node [RuboCop::AST::SendNode]
103
+ # @return [Boolean]
104
+ def bad?(node)
105
+ add_check_constraint?(node) &&
106
+ !add_check_constraint_with_validate_false?(node)
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end