ezcater_rubocop 7.1.2 → 8.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -1
- data/README.md +6 -1
- data/bin/check_configs.sh +23 -0
- 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,8 +6,16 @@ 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
|
+
|
9
17
|
## 7.1.2
|
10
|
-
|
18
|
+
|
11
19
|
- Fix a stray space in `Rails/BulkChangeTable` definition
|
12
20
|
|
13
21
|
## 7.1.1
|
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/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
|