ezcater_rubocop 7.1.1 → 8.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +6 -1
- data/bin/check_configs.sh +23 -0
- data/conf/rubocop_rails.yml +1 -1
- data/config/default.yml +5 -0
- data/lib/ezcater_rubocop/version.rb +1 -1
- data/lib/ezcater_rubocop.rb +17 -16
- data/lib/rubocop/cop/ezcater/migration/bigint_foreign_key.rb +264 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1a7228be76189e5a330bb1e9edae0e1bc35be77af84aebae08fd9b76f652283
|
4
|
+
data.tar.gz: 5727cedd1aa216879a69a06b02448a1eb3806e15ea82339d4ee5f14cfb87c162
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4cc8fd3788297b86403405edfc35e2b17ade3aa5a6656249021b022e41377cebd894ab45938204eefc556cb5585761ee89ecdf45c9613ce6256d99bcc06e0258
|
7
|
+
data.tar.gz: 844b539b44ffd246b2cc03af450d0239f2e3cd515e9e0ba7acdbd797b9cd229888ecd0ef1785faced9e7c06d82051690bc779e13d56c448afa57e000423b3d7c
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,18 @@ This gem is moving onto its own [Semantic Versioning](https://semver.org/) schem
|
|
6
6
|
|
7
7
|
Prior to v1.0.0 this gem was versioned based on the `MAJOR`.`MINOR` version of RuboCop. The first release of the ezcater_rubocop gem was `v0.49.0`.
|
8
8
|
|
9
|
+
## 8.0.0
|
10
|
+
|
11
|
+
- Add `Ezcater/Migration/BigintForeignKey` Cop, which enforces the use of `bigint` for foreign keys in migrations.
|
12
|
+
|
13
|
+
## 7.1.3
|
14
|
+
|
15
|
+
- Update internal CI processes to validate Rubocop config files
|
16
|
+
|
17
|
+
## 7.1.2
|
18
|
+
|
19
|
+
- Fix a stray space in `Rails/BulkChangeTable` definition
|
20
|
+
|
9
21
|
## 7.1.1
|
10
22
|
|
11
23
|
- Disable `Rails/BulkChangeTable` to avoid conflicts with `strong_migrations`
|
data/README.md
CHANGED
@@ -48,6 +48,10 @@ Further customization of RuboCop for your local project may be added to this fil
|
|
48
48
|
- **rubocop_gem**: For use in Ruby gem projects, this inherits from the **rubocop** configuration.
|
49
49
|
- **rubocop_rails**: For Rails projects, this inherits from the **rubocop** configuration.
|
50
50
|
|
51
|
+
### Documentation
|
52
|
+
|
53
|
+
Visit https://gemdocs.org/gems/ezcater_rubocop to view the documentation for our custom cops in the latest release.
|
54
|
+
|
51
55
|
## Usage
|
52
56
|
|
53
57
|
Run `rubocop` for an entire project:
|
@@ -92,8 +96,9 @@ not add cops with `enabled: false` unless you want that cop to always be disable
|
|
92
96
|
* [RspecRequireFeatureFlagMock](https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/rspec_require_feature_flag_mock.rb) - Enforce use of `mock_feature_flag` helper instead of mocking `FeatureFlag.is_active?` directly.
|
93
97
|
* [RspecRequireHttpStatusMatcher](https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/rspec_require_http_status_matcher.rb) - Use the HTTP status code matcher, like `expect(response).to have_http_status :bad_request`, rather than `expect(response.code).to eq 400`
|
94
98
|
* [StyleDig](https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/style_dig.rb) - Recommend `dig` for deeply nested access.
|
99
|
+
* [Migration/BigintForeignKey](https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/migration/bigint_foreign_key.rb) - Use `#bigint` instead of `#integer` for all foreign keys.
|
95
100
|
|
96
|
-
[GraphQL/NotAuthorizedScalarField]: https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/graphql/not_authorized_scalar_field.rb
|
101
|
+
[GraphQL/NotAuthorizedScalarField]: https://github.com/ezcater/ezcater_rubocop/blob/main/lib/rubocop/cop/ezcater/graphql/not_authorized_scalar_field.rb
|
97
102
|
|
98
103
|
## Development
|
99
104
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# Checks the validity of RuboCop config files in `conf/` directory (excluding the base config).
|
4
|
+
|
5
|
+
CONFIGS=(
|
6
|
+
"conf/rubocop_gem.yml"
|
7
|
+
"conf/rubocop_rails.yml"
|
8
|
+
)
|
9
|
+
|
10
|
+
exit_code=0
|
11
|
+
|
12
|
+
for config in "${CONFIGS[@]}"; do
|
13
|
+
if ! output=$(bundle exec rubocop --show-cops -c "$config" 2>&1); then
|
14
|
+
echo "❌ Error in $config"
|
15
|
+
echo "$output"
|
16
|
+
exit_code=1
|
17
|
+
fi
|
18
|
+
done
|
19
|
+
|
20
|
+
if [[ $exit_code -eq 0 ]]; then
|
21
|
+
echo "✅ All configs are valid"
|
22
|
+
fi
|
23
|
+
exit $exit_code
|
data/conf/rubocop_rails.yml
CHANGED
data/config/default.yml
CHANGED
data/lib/ezcater_rubocop.rb
CHANGED
@@ -16,19 +16,20 @@ puts "configuration from #{DEFAULT_FILES}" if RuboCop::ConfigLoader.debug?
|
|
16
16
|
config = RuboCop::ConfigLoader.merge_with_default(config, path)
|
17
17
|
RuboCop::ConfigLoader.instance_variable_set(:@default_configuration, config)
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
19
|
+
require_relative "rubocop/cop/ezcater/direct_env_check"
|
20
|
+
require_relative "rubocop/cop/ezcater/feature_flag_active"
|
21
|
+
require_relative "rubocop/cop/ezcater/feature_flag_name_valid"
|
22
|
+
require_relative "rubocop/cop/ezcater/graphql/not_authorized_scalar_field"
|
23
|
+
require_relative "rubocop/cop/ezcater/rails_configuration"
|
24
|
+
require_relative "rubocop/cop/ezcater/rails_env"
|
25
|
+
require_relative "rubocop/cop/ezcater/ruby_timeout"
|
26
|
+
require_relative "rubocop/cop/ezcater/rails_top_level_sql_execute"
|
27
|
+
require_relative "rubocop/cop/ezcater/require_custom_error"
|
28
|
+
require_relative "rubocop/cop/ezcater/require_gql_error_helpers"
|
29
|
+
require_relative "rubocop/cop/ezcater/rspec_match_ordered_array"
|
30
|
+
require_relative "rubocop/cop/ezcater/rspec_require_browser_mock"
|
31
|
+
require_relative "rubocop/cop/ezcater/rspec_require_feature_flag_mock"
|
32
|
+
require_relative "rubocop/cop/ezcater/rspec_require_http_status_matcher"
|
33
|
+
require_relative "rubocop/cop/ezcater/rspec_dot_not_self_dot"
|
34
|
+
require_relative "rubocop/cop/ezcater/style_dig"
|
35
|
+
require_relative "rubocop/cop/ezcater/migration/bigint_foreign_key"
|
@@ -0,0 +1,264 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Ezcater
|
6
|
+
module Migration
|
7
|
+
# Use `bigint` instead of `integer` for all foreign keys.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# create_table :foos do |t|
|
13
|
+
# t.integer :bar_id
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# create_table :foos do |t|
|
18
|
+
# t.integer :bar_id, limit: 7
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# # bad
|
22
|
+
# add_column :foos, :bar_id, :integer
|
23
|
+
#
|
24
|
+
# # bad
|
25
|
+
# add_column :foos, :bar_id, :integer, limit: 7
|
26
|
+
#
|
27
|
+
# # bad
|
28
|
+
# add_reference :foos, :bar, type: :integer
|
29
|
+
#
|
30
|
+
# # bad
|
31
|
+
# add_reference :foos, :bar, type: :integer, limit: 7
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# create_table :foos do |t|
|
35
|
+
# t.bigint :bar_id
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# # good
|
39
|
+
# create_table :foos do |t|
|
40
|
+
# t.references :bar
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# add_column :foos, :bar_id, :bigint
|
45
|
+
#
|
46
|
+
# # good
|
47
|
+
# add_reference :foos, :bar
|
48
|
+
#
|
49
|
+
class BigintForeignKey < Base # rubocop:disable Metrics/ClassLength
|
50
|
+
extend AutoCorrector
|
51
|
+
|
52
|
+
MSG = <<~MSG.chomp
|
53
|
+
Use `bigint` instead of `integer` for foreign keys. This ensures that they are capable of storing all possible values from referenced primary keys which are `bigint` or may eventually be migrated to `bigint`.
|
54
|
+
MSG
|
55
|
+
|
56
|
+
# Optimization: only call `on_send` for the methods in this list
|
57
|
+
RESTRICT_ON_SEND = %i(
|
58
|
+
integer
|
59
|
+
references
|
60
|
+
belongs_to
|
61
|
+
add_column
|
62
|
+
add_reference
|
63
|
+
add_belongs_to
|
64
|
+
).freeze
|
65
|
+
|
66
|
+
BIGINT_BYTES = 8
|
67
|
+
|
68
|
+
# @!method t_integer_method(node)
|
69
|
+
def_node_matcher :t_integer_method, <<~PATTERN
|
70
|
+
(send
|
71
|
+
# Any local variable that calls an `integer` method
|
72
|
+
(lvar _) :integer
|
73
|
+
|
74
|
+
# Column name: symbol or string ending in _id
|
75
|
+
{(sym #ends_with_id?) (str #ends_with_id?)}
|
76
|
+
|
77
|
+
# Optional hash that includes a limit key
|
78
|
+
(hash <(pair (sym :limit) (int $_)) ...>)?
|
79
|
+
)
|
80
|
+
PATTERN
|
81
|
+
|
82
|
+
# @!method t_references_method(node)
|
83
|
+
def_node_matcher :t_references_method, <<~PATTERN
|
84
|
+
(send
|
85
|
+
# Any local variable that calls a `references` or `belongs_to` method
|
86
|
+
(lvar _) {:references :belongs_to}
|
87
|
+
|
88
|
+
# Reference name
|
89
|
+
{(sym _) (str _)}
|
90
|
+
|
91
|
+
# A hash that includes `type: :integer`
|
92
|
+
(hash <(pair (sym :type) (sym :integer)) ...>)
|
93
|
+
)
|
94
|
+
PATTERN
|
95
|
+
|
96
|
+
# @!method add_column_method(node)
|
97
|
+
def_node_matcher :add_column_method, <<~PATTERN
|
98
|
+
# A call to an `add_column` method
|
99
|
+
(send nil? :add_column
|
100
|
+
# Table name
|
101
|
+
{(sym _) (str _)}
|
102
|
+
|
103
|
+
# Column name: a symbol or string ending in _id
|
104
|
+
{(sym #ends_with_id?) (str #ends_with_id?)}
|
105
|
+
|
106
|
+
# Column type
|
107
|
+
(sym :integer)
|
108
|
+
|
109
|
+
# Optional hash that includes a limit key
|
110
|
+
(hash <(pair (sym :limit) (int $_)) ...>)?
|
111
|
+
)
|
112
|
+
PATTERN
|
113
|
+
|
114
|
+
# @!method add_reference_method(node)
|
115
|
+
def_node_matcher :add_reference_method, <<~PATTERN
|
116
|
+
# A call to a `add_reference` or `add_belongs_to` method
|
117
|
+
(send nil? {:add_reference :add_belongs_to}
|
118
|
+
# Table name
|
119
|
+
{(sym _) (str _)}
|
120
|
+
|
121
|
+
# Reference name
|
122
|
+
{(sym _) (str _)}
|
123
|
+
|
124
|
+
# A hash that includes `type: :integer`
|
125
|
+
(hash <(pair (sym :type) (sym :integer)) ...>)
|
126
|
+
)
|
127
|
+
PATTERN
|
128
|
+
|
129
|
+
# @!method limit_pair(node)
|
130
|
+
def_node_search :limit_pair, <<~PATTERN
|
131
|
+
(pair (sym :limit) (int $_))
|
132
|
+
PATTERN
|
133
|
+
|
134
|
+
def on_send(node)
|
135
|
+
t_integer_method(node) do |captures|
|
136
|
+
check_integer_method(node, captures)
|
137
|
+
end
|
138
|
+
|
139
|
+
add_column_method(node) do |captures|
|
140
|
+
check_integer_method(node, captures)
|
141
|
+
end
|
142
|
+
|
143
|
+
t_references_method(node) do
|
144
|
+
check_reference_method(node)
|
145
|
+
end
|
146
|
+
|
147
|
+
add_reference_method(node) do
|
148
|
+
check_reference_method(node)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def ends_with_id?(str)
|
155
|
+
str.end_with?("_id")
|
156
|
+
end
|
157
|
+
|
158
|
+
def check_integer_method(node, captures)
|
159
|
+
limit_value = captures.first
|
160
|
+
check_for_offense(node, limit_value)
|
161
|
+
end
|
162
|
+
|
163
|
+
def check_reference_method(node)
|
164
|
+
limit_vals = limit_pair(node)
|
165
|
+
limit_value = limit_vals.first
|
166
|
+
|
167
|
+
check_for_offense(node, limit_value)
|
168
|
+
end
|
169
|
+
|
170
|
+
def check_for_offense(node, limit_value)
|
171
|
+
return unless limit_value.nil? || limit_value < BIGINT_BYTES
|
172
|
+
|
173
|
+
add_offense(node) do |corrector|
|
174
|
+
make_correction(node, corrector)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def make_correction(node, corrector)
|
179
|
+
case node.method_name
|
180
|
+
when :integer
|
181
|
+
correct_integer_method(node, corrector)
|
182
|
+
when :references, :belongs_to
|
183
|
+
correct_references_method(node, corrector)
|
184
|
+
when :add_column
|
185
|
+
correct_add_column_method(node, corrector)
|
186
|
+
when :add_reference, :add_belongs_to
|
187
|
+
correct_add_reference_method(node, corrector)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def correct_integer_method(node, corrector)
|
192
|
+
# There's no hash argument or it has only one pair
|
193
|
+
if node.arguments.size == 1 ||
|
194
|
+
(node.arguments.size == 2 &&
|
195
|
+
(node.arguments[1].hash_type? &&
|
196
|
+
node.arguments[1].pairs.size == 1))
|
197
|
+
|
198
|
+
corrector.replace(
|
199
|
+
range_for_method_and_optional_limit(node),
|
200
|
+
"bigint #{node.arguments[0].source}"
|
201
|
+
)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def correct_references_method(node, corrector)
|
206
|
+
# There's only one hash pair (:type) or only two: :type and :limit
|
207
|
+
return unless node.arguments.size == 2 && node.arguments[1].hash_type?
|
208
|
+
|
209
|
+
hash_pairs = node.arguments[1].pairs
|
210
|
+
keys = hash_pairs.map { |pair| pair.key.source }
|
211
|
+
|
212
|
+
if keys.size == 1 ||
|
213
|
+
(keys.size == 2 && keys.include?("limit"))
|
214
|
+
|
215
|
+
corrector.replace(
|
216
|
+
range_for_method_and_optional_limit(node),
|
217
|
+
"#{node.method_name} #{node.arguments[0].source}"
|
218
|
+
)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def correct_add_column_method(node, corrector)
|
223
|
+
# There's no hash argument or it has only one pair (:limit)
|
224
|
+
if node.arguments.size == 3 ||
|
225
|
+
(node.arguments.size == 4 &&
|
226
|
+
(node.arguments[3].hash_type? &&
|
227
|
+
node.arguments[3].pairs.size == 1))
|
228
|
+
|
229
|
+
corrector.replace(
|
230
|
+
range_for_method_and_optional_limit(node),
|
231
|
+
"add_column #{node.arguments[0].source}, #{node.arguments[1].source}, :bigint"
|
232
|
+
)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def correct_add_reference_method(node, corrector)
|
237
|
+
# There's only one hash pair (:type) or only two: :type and :limit
|
238
|
+
return unless node.arguments.size == 3 && node.arguments[2].hash_type?
|
239
|
+
|
240
|
+
hash_pairs = node.arguments[2].pairs
|
241
|
+
keys = hash_pairs.map { |pair| pair.key.source }
|
242
|
+
|
243
|
+
if keys.size == 1 ||
|
244
|
+
(keys.size == 2 && keys.include?("limit"))
|
245
|
+
|
246
|
+
corrector.replace(
|
247
|
+
range_for_method_and_optional_limit(node),
|
248
|
+
"#{node.method_name} #{node.arguments[0].source}, #{node.arguments[1].source}"
|
249
|
+
)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def range_for_method_and_optional_limit(node)
|
254
|
+
Parser::Source::Range.new(
|
255
|
+
node.source_range.source_buffer,
|
256
|
+
node.selector.begin_pos,
|
257
|
+
node.source_range.end_pos
|
258
|
+
)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ezcater_rubocop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 8.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ezCater, Inc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -205,6 +205,7 @@ files:
|
|
205
205
|
- Gemfile
|
206
206
|
- LICENSE.txt
|
207
207
|
- README.md
|
208
|
+
- bin/check_configs.sh
|
208
209
|
- bin/circle_rubocop.rb
|
209
210
|
- conf/rubocop.yml
|
210
211
|
- conf/rubocop_gem.yml
|
@@ -217,6 +218,7 @@ files:
|
|
217
218
|
- lib/rubocop/cop/ezcater/feature_flag_active.rb
|
218
219
|
- lib/rubocop/cop/ezcater/feature_flag_name_valid.rb
|
219
220
|
- lib/rubocop/cop/ezcater/graphql/not_authorized_scalar_field.rb
|
221
|
+
- lib/rubocop/cop/ezcater/migration/bigint_foreign_key.rb
|
220
222
|
- lib/rubocop/cop/ezcater/rails_configuration.rb
|
221
223
|
- lib/rubocop/cop/ezcater/rails_env.rb
|
222
224
|
- lib/rubocop/cop/ezcater/rails_top_level_sql_execute.rb
|