sevencop 0.22.0 → 0.24.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/Gemfile.lock +1 -1
  4. data/README.md +5 -16
  5. data/config/default.yml +16 -143
  6. data/lib/rubocop/cop/sevencop/rails_action_name.rb +61 -0
  7. data/lib/rubocop/cop/sevencop/rspec_describe_http_endpoint.rb +23 -10
  8. data/lib/sevencop/cop_concerns.rb +0 -3
  9. data/lib/sevencop/version.rb +1 -1
  10. data/lib/sevencop.rb +1 -16
  11. metadata +3 -21
  12. data/lib/rubocop/cop/sevencop/rails_migration_add_check_constraint.rb +0 -111
  13. data/lib/rubocop/cop/sevencop/rails_migration_add_column_with_default_value.rb +0 -229
  14. data/lib/rubocop/cop/sevencop/rails_migration_add_foreign_key.rb +0 -166
  15. data/lib/rubocop/cop/sevencop/rails_migration_add_index_concurrently.rb +0 -164
  16. data/lib/rubocop/cop/sevencop/rails_migration_batch_in_batches.rb +0 -95
  17. data/lib/rubocop/cop/sevencop/rails_migration_batch_in_transaction.rb +0 -83
  18. data/lib/rubocop/cop/sevencop/rails_migration_batch_with_throttling.rb +0 -108
  19. data/lib/rubocop/cop/sevencop/rails_migration_change_column.rb +0 -113
  20. data/lib/rubocop/cop/sevencop/rails_migration_change_column_null.rb +0 -128
  21. data/lib/rubocop/cop/sevencop/rails_migration_create_table_force.rb +0 -89
  22. data/lib/rubocop/cop/sevencop/rails_migration_jsonb.rb +0 -131
  23. data/lib/rubocop/cop/sevencop/rails_migration_remove_column.rb +0 -258
  24. data/lib/rubocop/cop/sevencop/rails_migration_rename_column.rb +0 -81
  25. data/lib/rubocop/cop/sevencop/rails_migration_rename_table.rb +0 -79
  26. data/lib/rubocop/cop/sevencop/rails_migration_reserved_word_mysql.rb +0 -232
  27. data/lib/rubocop/cop/sevencop/rails_migration_unique_index_columns_count.rb +0 -92
  28. data/lib/sevencop/cop_concerns/batch_processing.rb +0 -32
  29. data/lib/sevencop/cop_concerns/column_type_method.rb +0 -26
  30. data/lib/sevencop/cop_concerns/disable_ddl_transaction.rb +0 -49
@@ -1,258 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'active_support/inflector'
4
- require 'pathname'
5
-
6
- module RuboCop
7
- module Cop
8
- module Sevencop
9
- # Make sure the column is already ignored by the running app before removing it.
10
- #
11
- # Active Record caches database columns at runtime, so if you drop a column, it can cause exceptions until your app reboots.
12
- #
13
- # @safety
14
- # The logic to check if it is included in `ignored_columns` may fail.
15
- #
16
- # @example
17
- # # bad
18
- # class User < ApplicationRecord
19
- # end
20
- #
21
- # class RemoveUsersSomeColumn < ActiveRecord::Migration[7.0]
22
- # def change
23
- # remove_column :users, :some_column
24
- # end
25
- # end
26
- #
27
- # # good
28
- # class User < ApplicationRecord
29
- # self.ignored_columns += %w[some_column]
30
- # end
31
- #
32
- # class RemoveUsersSomeColumn < ActiveRecord::Migration[7.0]
33
- # def change
34
- # remove_column :users, :some_column
35
- # end
36
- # end
37
- class RailsMigrationRemoveColumn < RuboCop::Cop::Base
38
- MSG = 'Make sure the column is already ignored by the running app before removing it.'
39
-
40
- RESTRICT_ON_SEND = %i[
41
- remove_column
42
- ].freeze
43
-
44
- # @param node [RuboCop::AST::SendNode]
45
- # @return [void]
46
- def on_send(node)
47
- return unless bad?(node)
48
-
49
- add_offense(node)
50
- end
51
-
52
- private
53
-
54
- # @!method ignored_columns?(node)
55
- # @param node [RuboCop::AST::Node]
56
- # @return [Boolean]
57
- def_node_matcher :ignored_columns?, <<~PATTERN
58
- (send
59
- self
60
- :ignored_columns
61
- ...
62
- )
63
- PATTERN
64
-
65
- # @!method remove_column?(node)
66
- # @param node [RuboCop::AST::SendNode]
67
- # @return [Boolean]
68
- def_node_matcher :remove_column?, <<~PATTERN
69
- (send
70
- nil?
71
- :remove_column
72
- ...
73
- )
74
- PATTERN
75
-
76
- # @!method ignored_column_nodes_from(node)
77
- # @param node [RuboCop::AST::Node]
78
- # @return [Array<String, Symbol>, nil]
79
- def_node_matcher :ignored_column_nodes_from, <<~PATTERN
80
- `{
81
- (op_asgn
82
- (send
83
- self
84
- :ignored_columns
85
- ...
86
- )
87
- :+
88
- (array
89
- ({str sym} $_)*
90
- )
91
- )
92
-
93
- (send
94
- self
95
- :ignored_columns=
96
- (array
97
- ({str sym} $_)*
98
- )
99
- )
100
- }
101
- PATTERN
102
-
103
- # @param node [RuboCop::AST::SendNode]
104
- # @return [Boolean]
105
- def bad?(node)
106
- remove_column?(node) &&
107
- !ignored?(node)
108
- end
109
-
110
- # @param node [RuboCop::AST::SendNode]
111
- # @return [String, nil]
112
- def find_column_name_from(node)
113
- node.arguments[1].value&.to_s
114
- end
115
-
116
- # @param table_name [String]
117
- # @return [Array<String>]
118
- def find_ignored_column_names_from(table_name)
119
- pathname = model_pathname_from(
120
- singularize(table_name)
121
- )
122
- return [] unless pathname.exist?
123
-
124
- ignored_column_nodes = ignored_column_nodes_from(
125
- parse(
126
- content: pathname.read,
127
- path: pathname.to_s
128
- )
129
- )
130
- return [] unless ignored_column_nodes
131
-
132
- ignored_column_nodes.map(&:to_s)
133
- end
134
-
135
- # @param node [RuboCop::AST::SendNode]
136
- # @return [String, nil]
137
- def find_table_name_from(node)
138
- node.arguments[0].value&.to_s
139
- end
140
-
141
- # @param node [RuboCop::AST::SendNode]
142
- # @return [Boolean]
143
- def ignored?(node)
144
- find_ignored_column_names_from(
145
- find_table_name_from(node)
146
- ).include?(
147
- find_column_name_from(node)
148
- )
149
- end
150
-
151
- # @param snake_cased_model_name [String]
152
- # @return [Pathname]
153
- def model_pathname_from(snake_cased_model_name)
154
- ::Pathname.new("app/models/#{snake_cased_model_name}.rb")
155
- end
156
-
157
- # @param content [String]
158
- # @param path [String]
159
- # @return [RuboCop::AST::Node]
160
- def parse(
161
- content:,
162
- path:
163
- )
164
- Parser.call(
165
- content: content,
166
- path: path,
167
- target_ruby_version: target_ruby_version
168
- )
169
- end
170
-
171
- # @return [#parse]
172
- def parser
173
- parser_class.new(::RuboCop::AST::Builder.new)
174
- end
175
-
176
- # @return [Class]
177
- def parser_class
178
- ::Parser.const_get(
179
- "Ruby#{target_ruby_version.to_s.delete('.')}"
180
- )
181
- end
182
-
183
- # @param plural [String]
184
- # @return [String]
185
- def singularize(plural)
186
- ::ActiveSupport::Inflector.singularize(plural)
187
- end
188
-
189
- class Parser
190
- class << self
191
- # @param content [String]
192
- # @param path [String]
193
- # @param target_ruby_version [#to_s]
194
- # @return [RuboCop::AST::Node]
195
- def call(
196
- content:,
197
- path:,
198
- target_ruby_version:
199
- )
200
- new(
201
- content: content,
202
- path: path,
203
- target_ruby_version: target_ruby_version
204
- ).call
205
- end
206
- end
207
-
208
- # @param content [String]
209
- # @param path [String]
210
- # @param target_ruby_version [#to_s]
211
- def initialize(
212
- content:,
213
- path:,
214
- target_ruby_version:
215
- )
216
- @content = content
217
- @path = path
218
- @target_ruby_version = target_ruby_version
219
- end
220
-
221
- # @return [RuboCop::AST::Node]
222
- def call
223
- parser.parse(buffer)
224
- end
225
-
226
- private
227
-
228
- # @return [Parser::Source::Buffer]
229
- def buffer
230
- ::Parser::Source::Buffer.new(
231
- @path,
232
- source: @content
233
- )
234
- end
235
-
236
- # @return [RuboCop::AST::Builder]
237
- def builder
238
- ::RuboCop::AST::Builder.new
239
- end
240
-
241
- def parser
242
- parser_class.new(builder)
243
- end
244
-
245
- # @return [Class]
246
- def parser_class
247
- ::Parser.const_get(parser_class_name)
248
- end
249
-
250
- # @return [String]
251
- def parser_class_name
252
- "Ruby#{@target_ruby_version.to_s.delete('.')}"
253
- end
254
- end
255
- end
256
- end
257
- end
258
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Sevencop
6
- # Avoid renaming columns that are in use.
7
- #
8
- # It will cause errors in your application.
9
- # A safer approach is to:
10
- #
11
- # 1. Create a new column
12
- # 2. Write to both columns
13
- # 3. Backfill data from the old column to the new column
14
- # 4. Move reads from the old column to the new column
15
- # 5. Stop writing to the old column
16
- # 6. Drop the old column
17
- #
18
- # @safety
19
- # Only meaningful if the column is in use.
20
- #
21
- # @example
22
- # # bad
23
- # class RenameUsersSettingsToProperties < ActiveRecord::Migration[7.0]
24
- # def change
25
- # rename_column :users, :settings, :properties
26
- # end
27
- # end
28
- #
29
- # # good
30
- # class AddUsersProperties < ActiveRecord::Migration[7.0]
31
- # def change
32
- # add_column :users, :properties, :jsonb
33
- # end
34
- # end
35
- #
36
- # class User < ApplicationRecord
37
- # self.ignored_columns += %w[settings]
38
- # end
39
- #
40
- # class RemoveUsersSettings < ActiveRecord::Migration[7.0]
41
- # def change
42
- # remove_column :users, :settings
43
- # end
44
- # end
45
- class RailsMigrationRenameColumn < RuboCop::Cop::Base
46
- MSG = 'Avoid renaming columns that are in use.'
47
-
48
- RESTRICT_ON_SEND = %i[
49
- rename_column
50
- ].freeze
51
-
52
- # @param node [RuboCop::AST::SendNode]
53
- # @return [void]
54
- def on_send(node)
55
- return unless bad?(node)
56
-
57
- add_offense(node)
58
- end
59
-
60
- private
61
-
62
- # @!method rename_column?(node)
63
- # @param node [RuboCop::AST::SendNode]
64
- # @return [Boolean]
65
- def_node_matcher :rename_column?, <<~PATTERN
66
- (send
67
- nil?
68
- :rename_column
69
- ...
70
- )
71
- PATTERN
72
-
73
- # @param node [RuboCop::AST::SendNode]
74
- # @return [Boolean]
75
- def bad?(node)
76
- rename_column?(node)
77
- end
78
- end
79
- end
80
- end
81
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Sevencop
6
- # Avoid renaming tables that are in use.
7
- #
8
- # It will cause errors in your application.
9
- # A safer approach is to:
10
- #
11
- # 1. Create a new table
12
- # 2. Write to both tables
13
- # 3. Backfill data from the old table to new table
14
- # 4. Move reads from the old table to the new table
15
- # 5. Stop writing to the old table
16
- # 6. Drop the old table
17
- #
18
- # @safety
19
- # Only meaningful if the table is in use.
20
- #
21
- # @example
22
- # # bad
23
- # class RenameUsersToAccouts < ActiveRecord::Migration[7.0]
24
- # def change
25
- # rename_table :users, :accounts
26
- # end
27
- # end
28
- #
29
- # # good
30
- # class AddAccounts < ActiveRecord::Migration[7.0]
31
- # def change
32
- # create_table :accounts do |t|
33
- # t.string :name, null: false
34
- # end
35
- # end
36
- # end
37
- #
38
- # class RemoveUsers < ActiveRecord::Migration[7.0]
39
- # def change
40
- # remove_table :users
41
- # end
42
- # end
43
- class RailsMigrationRenameTable < RuboCop::Cop::Base
44
- MSG = 'Avoid renaming tables that are in use.'
45
-
46
- RESTRICT_ON_SEND = %i[
47
- rename_table
48
- ].freeze
49
-
50
- # @param node [RuboCop::AST::SendNode]
51
- # @return [void]
52
- def on_send(node)
53
- return unless bad?(node)
54
-
55
- add_offense(node)
56
- end
57
-
58
- private
59
-
60
- # @!method rename_table?(node)
61
- # @param node [RuboCop::AST::SendNode]
62
- # @return [Boolean]
63
- def_node_matcher :rename_table?, <<~PATTERN
64
- (send
65
- nil?
66
- :rename_table
67
- ...
68
- )
69
- PATTERN
70
-
71
- # @param node [RuboCop::AST::SendNode]
72
- # @return [Boolean]
73
- def bad?(node)
74
- rename_table?(node)
75
- end
76
- end
77
- end
78
- end
79
- end
@@ -1,232 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'set'
4
-
5
- module RuboCop
6
- module Cop
7
- module Sevencop
8
- # Avoid using MySQL reserved words as identifiers.
9
- #
10
- # @example
11
- # # bad
12
- # # NOTE: `role` is a reserved word in MySQL.
13
- # add_column :users, :role, :string
14
- #
15
- # # good
16
- # add_column :users, :some_other_good_name, :string
17
- class RailsMigrationReservedWordMysql < RuboCop::Cop::Base
18
- include ::Sevencop::CopConcerns::ColumnTypeMethod
19
-
20
- MSG = 'Avoid using MySQL reserved words as identifiers.'
21
-
22
- # Obtained from https://dev.mysql.com/doc/refman/8.0/en/keywords.html.
23
- PATH_TO_RESERVED_WORDS_FILE = File.expand_path(
24
- '../../../../data/reserved_words_mysql.txt',
25
- __dir__
26
- ).freeze
27
-
28
- RESTRICT_ON_SEND = [
29
- :add_column,
30
- :add_index,
31
- :add_reference,
32
- :create_join_table,
33
- :create_table,
34
- :rename,
35
- :rename_column,
36
- :rename_index,
37
- :rename_table,
38
- *COLUMN_TYPE_METHOD_NAMES
39
- ].freeze
40
-
41
- class << self
42
- # @return [Array<String>]
43
- def reserved_words
44
- @reserved_words ||= ::Set.new(
45
- ::File.read(PATH_TO_RESERVED_WORDS_FILE).split("\n")
46
- ).freeze
47
- end
48
- end
49
-
50
- # @param node [RuboCop::AST::DefNode]
51
- # @return [void]
52
- def on_send(node)
53
- offended_identifier_nodes_from(node).each do |identifier_node|
54
- add_offense(identifier_node)
55
- end
56
- end
57
-
58
- private
59
-
60
- # @!method index_name_option_from_add_index(node)
61
- # @param node [RuboCop::AST::SendNode]
62
- # @return [RuboCop::AST::Node, nil]
63
- def_node_matcher :index_name_option_from_add_index, <<~PATTERN
64
- (send
65
- nil?
66
- :add_index
67
- _
68
- _
69
- (hash
70
- <
71
- (pair
72
- (sym :name)
73
- $_
74
- )
75
- >
76
- ...
77
- )
78
- )
79
- PATTERN
80
-
81
- # @!method index_name_option_from_add_reference(node)
82
- # @param node [RuboCop::AST::SendNode]
83
- # @return [RuboCop::AST::Node, nil]
84
- def_node_matcher :index_name_option_from_add_reference, <<~PATTERN
85
- (send
86
- nil?
87
- :add_reference
88
- _
89
- _
90
- (hash
91
- <
92
- (pair
93
- (sym :index)
94
- (hash
95
- <
96
- (pair
97
- (sym :name)
98
- $_
99
- )
100
- >
101
- ...
102
- )
103
- )
104
- >
105
- ...
106
- )
107
- )
108
- PATTERN
109
-
110
- # @!method index_name_option_from_column_type(node)
111
- # @param node [RuboCop::AST::SendNode]
112
- # @return [RuboCop::AST::Node, nil]
113
- def_node_matcher :index_name_option_from_column_type, <<~PATTERN
114
- (send
115
- lvar
116
- COLUMN_TYPE_METHOD_NAMES
117
- _
118
- (hash
119
- <
120
- (pair
121
- (sym :index)
122
- (hash
123
- <
124
- (pair
125
- (sym :name)
126
- $_
127
- )
128
- ...
129
- >
130
- )
131
- )
132
- ...
133
- >
134
- )
135
- )
136
- PATTERN
137
-
138
- # @!method table_name_option_from(node)
139
- # @param node [RuboCop::AST::SendNode]
140
- # @return [RuboCop::AST::Node, nil]
141
- def_node_matcher :table_name_option_from, <<~PATTERN
142
- (send
143
- nil?
144
- :create_join_table
145
- _
146
- _
147
- (hash
148
- <
149
- (pair
150
- (sym :table_name)
151
- $_
152
- )
153
- ...
154
- >
155
- )
156
- )
157
- PATTERN
158
-
159
- # @param node [RuboCop::AST::SendNode]
160
- # @return [Array<RuboCop::AST::Node>]
161
- def identifier_column_name_nodes_from(node)
162
- case node.method_name
163
- when :add_column, :rename
164
- [node.arguments[1]]
165
- when :rename_column
166
- [node.arguments[2]]
167
- when *COLUMN_TYPE_METHOD_NAMES
168
- [node.arguments[0]]
169
- else
170
- []
171
- end
172
- end
173
-
174
- # @param node [RuboCop::AST::SendNode]
175
- # @return [Array<RuboCop::AST::Node>]
176
- def identifier_index_name_nodes_from(node)
177
- case node.method_name
178
- when :add_index
179
- [index_name_option_from_add_index(node)].compact
180
- when :add_reference
181
- [index_name_option_from_add_reference(node)].compact
182
- when :rename_index
183
- [node.arguments[2]]
184
- when *COLUMN_TYPE_METHOD_NAMES
185
- [index_name_option_from_column_type(node)].compact
186
- else
187
- []
188
- end
189
- end
190
-
191
- # @param node [RuboCop::AST::SendNode]
192
- # @return [Array<RuboCop::AST::Node>]
193
- def identifier_nodes_from(node)
194
- identifier_table_name_nodes_from(node) +
195
- identifier_column_name_nodes_from(node) +
196
- identifier_index_name_nodes_from(node)
197
- end
198
-
199
- # @param node [RuboCop::AST::SendNode]
200
- # @return [Array<RuboCop::AST::Node>]
201
- def identifier_table_name_nodes_from(node)
202
- case node.method_name
203
- when :create_join_table
204
- [table_name_option_from(node)].compact
205
- when :create_table
206
- [node.arguments[0]]
207
- when :rename_table
208
- [node.arguments[1]]
209
- else
210
- []
211
- end
212
- end
213
-
214
- # @param node [RuboCop::AST::Node]
215
- # @return [Array<RuboCop::AST::Node>]
216
- def offended_identifier_nodes_from(node)
217
- identifier_nodes_from(node).select do |identifier_node|
218
- reserved_word_identifier_node?(identifier_node)
219
- end
220
- end
221
-
222
- # @param node [RuboCop::AST::Node]
223
- # @return [Boolean]
224
- def reserved_word_identifier_node?(node)
225
- return false unless node.respond_to?(:value)
226
-
227
- self.class.reserved_words.include?(node.value.to_s)
228
- end
229
- end
230
- end
231
- end
232
- end