rubocop-migration 0.3.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d5fe85da04542f564b53e8c0d779c4258ca907f99a7583919aa02007d719f33
4
- data.tar.gz: 06bd03d9e0afdf5618ad2bdfffbfa2ac465821f65009e2c949051bd04e3defae
3
+ metadata.gz: fa5e7fda6eeffbf26f8c9bd1a4433a689416e0a2098ce9193f93c72564b8b4f2
4
+ data.tar.gz: 4907939dbd5ba1a39cf76d838824bfa8574fe527b6a8985588bd7897eb5a3a1c
5
5
  SHA512:
6
- metadata.gz: 5943d60b5a214eecc77d326cf94b7f44fb270592822687f05b7165ca4b6165086ae6491f523a27dab620fb3e83ee6c7e03058d14b93cbecbc9dcf1334c47f333
7
- data.tar.gz: 7b20c8d2766ff2803ae32a31f598e447fa5fd4282c9507fded7181d5c85d139fe8de603f6000e4dbe49c73b963a07f6cef12b8ec248eba925a621024086c2b86
6
+ metadata.gz: 6885d3a799806f1a3699cf892eb2a9855b66b8d29f9578fe9a0d8f98e84ab0526683710a35b22dbb1601cc6b52c015421aa163c6f671a4366ceb3d5a582dedba
7
+ data.tar.gz: 8838e0d3758231c59a844e26d4b7795dd7abf74743a16f25075f9804f3de51248d2c6893614ecfdee8cdf075af46430b3723b3e10f62a57a39f42ef31b326489
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rubocop-migration (0.3.2)
4
+ rubocop-migration (0.4.1)
5
5
  activesupport
6
6
  rubocop (>= 1.34)
7
7
  rubocop-rails
@@ -9,22 +9,22 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- activesupport (7.0.4)
12
+ activesupport (7.0.5)
13
13
  concurrent-ruby (~> 1.0, >= 1.0.2)
14
14
  i18n (>= 1.6, < 2)
15
15
  minitest (>= 5.1)
16
16
  tzinfo (~> 2.0)
17
17
  ast (2.4.2)
18
- concurrent-ruby (1.1.10)
18
+ concurrent-ruby (1.2.2)
19
19
  diff-lcs (1.5.0)
20
- i18n (1.12.0)
20
+ i18n (1.14.1)
21
21
  concurrent-ruby (~> 1.0)
22
22
  json (2.6.2)
23
- minitest (5.16.3)
23
+ minitest (5.18.0)
24
24
  parallel (1.22.1)
25
25
  parser (3.1.2.1)
26
26
  ast (~> 2.4.1)
27
- rack (3.0.0)
27
+ rack (3.0.7)
28
28
  rainbow (3.1.1)
29
29
  rake (13.0.6)
30
30
  regexp_parser (2.6.0)
@@ -57,7 +57,7 @@ GEM
57
57
  rubocop-performance (1.15.0)
58
58
  rubocop (>= 1.7.0, < 2.0)
59
59
  rubocop-ast (>= 0.4.0)
60
- rubocop-rails (2.16.1)
60
+ rubocop-rails (2.19.1)
61
61
  activesupport (>= 4.2.0)
62
62
  rack (>= 1.1)
63
63
  rubocop (>= 1.33.0, < 2.0)
@@ -68,7 +68,7 @@ GEM
68
68
  ruby-progressbar (1.11.0)
69
69
  sevencop (0.21.0)
70
70
  rubocop
71
- tzinfo (2.0.5)
71
+ tzinfo (2.0.6)
72
72
  concurrent-ruby (~> 1.0)
73
73
  unicode-display_width (2.3.0)
74
74
 
data/README.md CHANGED
@@ -6,14 +6,11 @@ RuboCop extension focused on ActiveRecord migration.
6
6
 
7
7
  ## Usage
8
8
 
9
- ~~Install `rubocop-migration` gem:~~
10
-
11
- This gem is not yet published to rubygems.org.
12
- See [#1](https://github.com/r7kamura/rubocop-migration/issues/1) for more details.
9
+ Install `rubocop-migration` gem:
13
10
 
14
11
  ```ruby
15
12
  # Gemfile
16
- gem 'rubocop-migration', require: false, github: 'r7kamura/rubocop-migration', tag: 'v0.3.1'
13
+ gem 'rubocop-migration', require: false
17
14
  ```
18
15
 
19
16
  then require `rubocop-migration` and enable the cops you want to use in your .rubocop.yml:
@@ -24,7 +21,7 @@ require:
24
21
  - rubocop-migration
25
22
 
26
23
  Migration/AddCheckConstraint:
27
- Enabled: false
24
+ Enabled: true
28
25
  ```
29
26
 
30
27
  Note that all cops are `Enabled: false` by default.
@@ -53,6 +50,8 @@ Please read the comments of the respective cop classes for more information.
53
50
 
54
51
  ## Acknowledgements
55
52
 
56
- This gem was heavily inspired by the following gem:
53
+ This gem was heavily inspired by [ankane/strong_migrations](https://github.com/ankane/strong_migrations).
54
+
55
+ The gem `rubocop-migration` was originally developed at [wealthsimple/rubocop-migration](https://github.com/wealthsimple/rubocop-migration), and later the gem name was transferred to this repository.
57
56
 
58
- - [ankane/strong_migrations](https://github.com/ankane/strong_migrations)
57
+ Some cops were originally created at [r7kamura/sevencop](https://github.com/r7kamura/sevencop) then moved to this repository.
@@ -30,9 +30,12 @@ module RuboCop
30
30
  extend AutoCorrector
31
31
 
32
32
  include ::RuboCop::Migration::CopConcerns::DisableDdlTransaction
33
+ include RangeHelp
33
34
 
34
35
  MSG = 'Use `algorithm: :concurrently` on adding indexes to existing tables in PostgreSQL.'
35
36
 
37
+ MESSAGE_FOR_DUPLICATED_DISABLE_DDL_TRANSACTION = 'Remove duplicated `disable_ddl_transaction!`.'
38
+
36
39
  RESTRICT_ON_SEND = %i[
37
40
  add_index
38
41
  index
@@ -41,10 +44,21 @@ module RuboCop
41
44
  # @param node [RuboCop::AST::SendNode]
42
45
  # @return [void]
43
46
  def on_send(node)
44
- return unless bad?(node)
47
+ if add_index_without_concurrency?(node)
48
+ add_offense(node) do |corrector|
49
+ autocorrect(corrector, node)
50
+ end
51
+ end
45
52
 
46
- add_offense(node) do |corrector|
47
- autocorrect(corrector, node)
53
+ duplicated_disable_ddl_transactions_from(node).each do |disable_ddl_transactions_node|
54
+ add_offense(node, message: MESSAGE_FOR_DUPLICATED_DISABLE_DDL_TRANSACTION) do |corrector|
55
+ corrector.remove(
56
+ range_with_surrounding_space(
57
+ disable_ddl_transactions_node.source_range,
58
+ side: :left
59
+ )
60
+ )
61
+ end
48
62
  end
49
63
  end
50
64
 
@@ -116,6 +130,17 @@ module RuboCop
116
130
  )
117
131
  PATTERN
118
132
 
133
+ # @param node [RuboCop::AST::SendNode]
134
+ # @return [Boolean]
135
+ def add_index_without_concurrency?(node)
136
+ case node.method_name
137
+ when :add_index
138
+ add_index?(node) && !add_index_concurrently?(node)
139
+ when :index
140
+ index?(node) && in_change_table?(node) && !index_concurrently?(node)
141
+ end
142
+ end
143
+
119
144
  # @param corrector [RuboCop::Cop::Corrector]
120
145
  # @param node [RuboCop::AST::SendNode]
121
146
  # @return [void]
@@ -128,14 +153,9 @@ module RuboCop
128
153
  end
129
154
 
130
155
  # @param node [RuboCop::AST::SendNode]
131
- # @return [Boolean]
132
- def bad?(node)
133
- case node.method_name
134
- when :add_index
135
- add_index?(node) && !add_index_concurrently?(node)
136
- when :index
137
- index?(node) && in_change_table?(node) && !index_concurrently?(node)
138
- end
156
+ # @return [Array<RuboCop::AST::SendNode>]
157
+ def duplicated_disable_ddl_transactions_from(node)
158
+ disable_ddl_transactions_from(node)[1..] || []
139
159
  end
140
160
 
141
161
  # @param node [RuboCop::AST::SendNode]
@@ -40,12 +40,13 @@ module RuboCop
40
40
 
41
41
  RESTRICT_ON_SEND = %i[
42
42
  change_column_null
43
+ change_null
43
44
  ].freeze
44
45
 
45
46
  # @param node [RuboCop::AST::SendNode]
46
47
  # @return [void]
47
48
  def on_send(node)
48
- return if in_second_migration?(node)
49
+ return if called_with_validate_constraint?(node)
49
50
 
50
51
  add_offense(node) do |corrector|
51
52
  autocorrect(corrector, node)
@@ -54,26 +55,6 @@ module RuboCop
54
55
 
55
56
  private
56
57
 
57
- # @!method parse_table_name_and_column_name(node)
58
- # @param node [RuboCop::AST::SendNode]
59
- # @return [Array<Symbol>, nil]
60
- def_node_matcher :parse_table_name_and_column_name, <<~PATTERN
61
- (send
62
- nil?
63
- _
64
- ({str sym} $_)
65
- ({str sym} $_)
66
- ...
67
- )
68
- PATTERN
69
-
70
- # @!method remove_check_constraint?(node)
71
- # @param node [RuboCop::AST::SendNode]
72
- # @return [Boolean]
73
- def_node_matcher :remove_check_constraint?, <<~PATTERN
74
- (send nil? :remove_check_constraint ...)
75
- PATTERN
76
-
77
58
  # @!method validate_constraint?(node)
78
59
  # @param node [RuboCop::AST::SendNode]
79
60
  # @return [Boolean]
@@ -88,39 +69,138 @@ module RuboCop
88
69
  corrector,
89
70
  node
90
71
  )
91
- table_name, column_name = parse_table_name_and_column_name(node)
72
+ case node.method_name
73
+ when :change_column_null
74
+ autocorrect_change_column_null(corrector, node)
75
+ when :change_null
76
+ autocorrect_change_null(corrector, node)
77
+ end
78
+ end
79
+
80
+ # @param corrector [RuboCop::Cop::Corrector]
81
+ # @param node [RuboCop::AST::SendNode]
82
+ # @return [void]
83
+ def autocorrect_change_column_null(
84
+ corrector,
85
+ node
86
+ )
92
87
  corrector.replace(
93
88
  node,
94
- format(
95
- "add_check_constraint :%<table>s, '%<column>s IS NOT NULL', name: '%<constraint>s', validate: false",
96
- column: column_name,
97
- constraint: "#{table_name}_#{column_name}_is_not_null",
98
- table: table_name
89
+ format_add_check_constraint(
90
+ column_name: find_column_name_from_change_column_null(node),
91
+ table_name: find_table_name_from_change_column_null(node)
92
+ )
93
+ )
94
+ end
95
+
96
+ # @param corrector [RuboCop::Cop::Corrector]
97
+ # @param node [RuboCop::AST::SendNode]
98
+ # @return [void]
99
+ def autocorrect_change_null(
100
+ corrector,
101
+ node
102
+ )
103
+ corrector.replace(
104
+ node.location.selector.with(
105
+ end_pos: node.location.expression.end_pos
106
+ ),
107
+ format_check_constraint(
108
+ column_name: find_column_name_from_change_null(node),
109
+ table_name: find_table_name_from_change_null(node)
99
110
  )
100
111
  )
101
112
  end
102
113
 
103
114
  # @param node [RuboCop::AST::SendNode]
104
115
  # @return [Boolean]
105
- def called_after_validate_constraint?(node)
106
- node.left_siblings.any? do |sibling|
116
+ def called_with_validate_constraint?(node)
117
+ case node.method_name
118
+ when :change_column_null
119
+ node
120
+ when :change_null
121
+ find_ancestor_change_table(node)
122
+ end.left_siblings.any? do |sibling|
107
123
  validate_constraint?(sibling)
108
124
  end
109
125
  end
110
126
 
111
127
  # @param node [RuboCop::AST::SendNode]
112
- # @return [Boolean]
113
- def called_before_remove_check_constraint?(node)
114
- node.right_siblings.any? do |sibling|
115
- remove_check_constraint?(sibling)
128
+ # @return [RuboCop::AST::BlockNode]
129
+ def find_ancestor_change_table(node)
130
+ node.each_ancestor(:block).find do |ancestor|
131
+ ancestor.method?(:change_table)
116
132
  end
117
133
  end
118
134
 
119
135
  # @param node [RuboCop::AST::SendNode]
120
- # @return [Boolean]
121
- def in_second_migration?(node)
122
- called_after_validate_constraint?(node) ||
123
- called_before_remove_check_constraint?(node)
136
+ # @return [String]
137
+ def find_column_name_from_change_column_null(node)
138
+ node.arguments[1].value.to_s
139
+ end
140
+
141
+ # @param node [RuboCop::AST::SendNode]
142
+ # @return [String]
143
+ def find_column_name_from_change_null(node)
144
+ node.arguments[0].value.to_s
145
+ end
146
+
147
+ # @parm node [RuboCop::AST::SendNode]
148
+ # @return [String]
149
+ def find_table_name_from_change_column_null(node)
150
+ node.arguments[0].value.to_s
151
+ end
152
+
153
+ # @param node [RuboCop::AST::SendNode]
154
+ # @return [String]
155
+ def find_table_name_from_change_null(node)
156
+ find_ancestor_change_table(node).send_node.arguments[0].value.to_s
157
+ end
158
+
159
+ # @param column_name [String]
160
+ # @param table_name [String]
161
+ # @return [String]
162
+ def format_add_check_constraint(
163
+ column_name:,
164
+ table_name:
165
+ )
166
+ format(
167
+ 'add_check_constraint :%<table_name>s, %<arguments>s',
168
+ arguments: format_check_constraint_arguments(
169
+ column_name: column_name,
170
+ table_name: table_name
171
+ ),
172
+ table_name: table_name
173
+ )
174
+ end
175
+
176
+ # @param column_name [String]
177
+ # @param table_name [String]
178
+ # @return [String]
179
+ def format_check_constraint(
180
+ column_name:,
181
+ table_name:
182
+ )
183
+ format(
184
+ 'check_constraint %<arguments>s',
185
+ arguments: format_check_constraint_arguments(
186
+ column_name: column_name,
187
+ table_name: table_name
188
+ )
189
+ )
190
+ end
191
+
192
+ # @param coumn_name [String]
193
+ # @param table_name [String]
194
+ # @return [String]
195
+ def format_check_constraint_arguments(
196
+ column_name:,
197
+ table_name:
198
+ )
199
+ format(
200
+ "'%<column_name>s IS NOT NULL', name: '%<constraint_name>s', validate: false",
201
+ column_name: column_name,
202
+ constraint_name: "#{table_name}_#{column_name}_is_not_null"
203
+ )
124
204
  end
125
205
  end
126
206
  end
@@ -24,6 +24,15 @@ module RuboCop
24
24
 
25
25
  private
26
26
 
27
+ # @param node [RuboCop::AST::SendNode]
28
+ # @return [Array<RuboCop::AST::SendNode>]
29
+ def disable_ddl_transactions_from(node)
30
+ node.each_ancestor(:def).first&.left_siblings&.select do |sibling|
31
+ sibling.is_a?(::RuboCop::AST::SendNode) &&
32
+ disable_ddl_transaction?(sibling)
33
+ end || []
34
+ end
35
+
27
36
  # @param corrector [RuboCop::Cop::Corrector]
28
37
  # @param node [RuboCop::AST::SendNode]
29
38
  # @return [void]
@@ -40,10 +49,7 @@ module RuboCop
40
49
  # @param node [RuboCop::AST::SendNode]
41
50
  # @return [Boolean]
42
51
  def within_disable_ddl_transaction?(node)
43
- node.each_ancestor(:def).first&.left_siblings&.any? do |sibling|
44
- sibling.is_a?(::RuboCop::AST::SendNode) &&
45
- disable_ddl_transaction?(sibling)
46
- end
52
+ !disable_ddl_transactions_from(node).empty?
47
53
  end
48
54
  end
49
55
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rubocop
4
4
  module Migration
5
- VERSION = '0.3.2'
5
+ VERSION = '0.4.1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-migration
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryo Nakamura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-19 00:00:00.000000000 Z
11
+ date: 2023-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -61,7 +61,6 @@ extra_rdoc_files: []
61
61
  files:
62
62
  - ".rspec"
63
63
  - ".rubocop.yml"
64
- - CHANGELOG.md
65
64
  - CODE_OF_CONDUCT.md
66
65
  - Gemfile
67
66
  - Gemfile.lock
@@ -118,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
117
  - !ruby/object:Gem::Version
119
118
  version: '0'
120
119
  requirements: []
121
- rubygems_version: 3.3.7
120
+ rubygems_version: 3.3.26
122
121
  signing_key:
123
122
  specification_version: 4
124
123
  summary: RuboCop extension focused on ActiveRecord migration.
data/CHANGELOG.md DELETED
@@ -1,5 +0,0 @@
1
- ## [Unreleased]
2
-
3
- ## [0.1.0] - 2022-10-17
4
-
5
- - Initial release