rubocop-yiffspace 0.0.1
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 +7 -0
- data/.idea/.gitignore +8 -0
- data/.idea/jsonSchemas.xml +25 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/rubocop-plugin.iml +65 -0
- data/.idea/vcs.xml +6 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +33 -0
- data/config/custom.yml +17 -0
- data/config/default.yml +54 -0
- data/config/rails.yml +8 -0
- data/config/shared/bundler.yml +1 -0
- data/config/shared/gemspec.yml +1 -0
- data/config/shared/layout.yml +18 -0
- data/config/shared/lint.yml +4 -0
- data/config/shared/metrics.yml +35 -0
- data/config/shared/migration.yml +1 -0
- data/config/shared/naming.yml +7 -0
- data/config/shared/rails.yml +14 -0
- data/config/shared/security.yml +1 -0
- data/config/shared/style.yml +45 -0
- data/config/shared.yml +12 -0
- data/lib/rubocop/cop/mixin/active_record_helper.rb +18 -0
- data/lib/rubocop/cop/mixin/node_formatting_helper.rb +59 -0
- data/lib/rubocop/cop/yiff_space/belongs_to_user.rb +121 -0
- data/lib/rubocop/cop/yiff_space/belongs_to_user_invalid_ip.rb +107 -0
- data/lib/rubocop/cop/yiff_space/belongs_to_user_missing_ip.rb +105 -0
- data/lib/rubocop/cop/yiff_space/current_user_outside_of_requests.rb +194 -0
- data/lib/rubocop/cop/yiff_space/resolvable_user.rb +113 -0
- data/lib/rubocop/cop/yiff_space/user_to_id.rb +64 -0
- data/lib/rubocop/cop/yiffspace_cops.rb +10 -0
- data/lib/rubocop/yiff_space/plugin.rb +31 -0
- data/lib/rubocop/yiff_space/version.rb +7 -0
- data/lib/rubocop/yiff_space.rb +8 -0
- data/lib/rubocop-yiffspace.rb +9 -0
- data/spec/rubocop/cop/yiff_space/belongs_to_user_invalid_ip_spec.rb +109 -0
- data/spec/rubocop/cop/yiff_space/belongs_to_user_missing_ip_spec.rb +91 -0
- data/spec/rubocop/cop/yiff_space/belongs_to_user_spec.rb +158 -0
- data/spec/rubocop/cop/yiff_space/current_user_outside_of_requests_spec.rb +398 -0
- data/spec/rubocop/cop/yiff_space/resolvable_user_spec.rb +99 -0
- data/spec/rubocop/cop/yiff_space/user_to_id_spec.rb +67 -0
- data/spec/spec_helper.rb +20 -0
- metadata +118 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe(RuboCop::Cop::YiffSpace::CurrentUserOutsideOfRequests, :config) do
|
|
4
|
+
let(:config) do
|
|
5
|
+
RuboCop::Config.new(
|
|
6
|
+
"YiffSpace/CurrentUserOutsideOfRequests" => {
|
|
7
|
+
"ClassName" => "CurrentUser",
|
|
8
|
+
"IgnoredMethods" => [],
|
|
9
|
+
"IgnoredMethodPrefixes" => [],
|
|
10
|
+
"IgnoredMethodSuffixes" => [],
|
|
11
|
+
"IgnoredMethodPatterns" => [],
|
|
12
|
+
},
|
|
13
|
+
)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it("registers an offense for CurrentUser.method calls in a regular method") do
|
|
17
|
+
expect_offense(<<~RUBY)
|
|
18
|
+
def process
|
|
19
|
+
CurrentUser.id
|
|
20
|
+
^^^^^^^^^^^^^^ `CurrentUser` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
21
|
+
end
|
|
22
|
+
RUBY
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it("registers an offense for a bare CurrentUser constant reference") do
|
|
26
|
+
expect_offense(<<~RUBY)
|
|
27
|
+
def process
|
|
28
|
+
user = CurrentUser
|
|
29
|
+
^^^^^^^^^^^ `CurrentUser` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
30
|
+
end
|
|
31
|
+
RUBY
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it("does not register an offense when CurrentUser is used inside its own class definition") do
|
|
35
|
+
expect_no_offenses(<<~RUBY)
|
|
36
|
+
class CurrentUser
|
|
37
|
+
def self.id
|
|
38
|
+
RequestStore[:current_user]&.id
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
RUBY
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it("does not register an offense inside a qualified class definition matching ClassName") do
|
|
45
|
+
expect_no_offenses(<<~RUBY)
|
|
46
|
+
class Logical::CurrentUser
|
|
47
|
+
def self.email
|
|
48
|
+
RequestStore[:current_user]&.email
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
RUBY
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context("when ClassName is a fully-qualified nested constant") do
|
|
55
|
+
let(:config) do
|
|
56
|
+
RuboCop::Config.new(
|
|
57
|
+
"YiffSpace/CurrentUserOutsideOfRequests" => {
|
|
58
|
+
"ClassName" => "Logical::CurrentUser",
|
|
59
|
+
"IgnoredMethods" => [],
|
|
60
|
+
"IgnoredMethodPrefixes" => [],
|
|
61
|
+
"IgnoredMethodSuffixes" => [],
|
|
62
|
+
"IgnoredMethodPatterns" => [],
|
|
63
|
+
},
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it("does not register an offense inside the matching nested class definition") do
|
|
68
|
+
expect_no_offenses(<<~RUBY)
|
|
69
|
+
module Logical
|
|
70
|
+
class CurrentUser
|
|
71
|
+
def self.email
|
|
72
|
+
RequestStore[:current_user]&.email
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
RUBY
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it("does not register an offense for a bare CurrentUser reference outside the Logical namespace") do
|
|
80
|
+
expect_no_offenses(<<~RUBY)
|
|
81
|
+
def process
|
|
82
|
+
CurrentUser.id
|
|
83
|
+
end
|
|
84
|
+
RUBY
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it("registers an offense for CurrentUser inside the Logical namespace") do
|
|
88
|
+
expect_offense(<<~RUBY)
|
|
89
|
+
module Logical
|
|
90
|
+
def self.process
|
|
91
|
+
CurrentUser.id
|
|
92
|
+
^^^^^^^^^^^^^^ `Logical::CurrentUser` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
RUBY
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it("registers an offense even when deeply nested in another class") do
|
|
100
|
+
expect_offense(<<~RUBY)
|
|
101
|
+
class PostService
|
|
102
|
+
def call
|
|
103
|
+
CurrentUser.id
|
|
104
|
+
^^^^^^^^^^^^^^ `CurrentUser` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
RUBY
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
context("with IgnoredMethods") do
|
|
111
|
+
let(:config) do
|
|
112
|
+
RuboCop::Config.new(
|
|
113
|
+
"YiffSpace/CurrentUserOutsideOfRequests" => {
|
|
114
|
+
"ClassName" => "CurrentUser",
|
|
115
|
+
"IgnoredMethods" => ["serializable_hash"],
|
|
116
|
+
"IgnoredMethodPrefixes" => [],
|
|
117
|
+
"IgnoredMethodSuffixes" => [],
|
|
118
|
+
"IgnoredMethodPatterns" => [],
|
|
119
|
+
},
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it("does not register an offense in an ignored method") do
|
|
124
|
+
expect_no_offenses(<<~RUBY)
|
|
125
|
+
def serializable_hash
|
|
126
|
+
CurrentUser.id
|
|
127
|
+
end
|
|
128
|
+
RUBY
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it("still registers an offense in a non-ignored method") do
|
|
132
|
+
expect_offense(<<~RUBY)
|
|
133
|
+
def process
|
|
134
|
+
CurrentUser.id
|
|
135
|
+
^^^^^^^^^^^^^^ `CurrentUser` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
136
|
+
end
|
|
137
|
+
RUBY
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context("with IgnoredMethodPrefixes") do
|
|
142
|
+
let(:config) do
|
|
143
|
+
RuboCop::Config.new(
|
|
144
|
+
"YiffSpace/CurrentUserOutsideOfRequests" => {
|
|
145
|
+
"ClassName" => "CurrentUser",
|
|
146
|
+
"IgnoredMethods" => [],
|
|
147
|
+
"IgnoredMethodPrefixes" => ["apionly_"],
|
|
148
|
+
"IgnoredMethodSuffixes" => [],
|
|
149
|
+
"IgnoredMethodPatterns" => [],
|
|
150
|
+
},
|
|
151
|
+
)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it("does not register an offense in a method matching the prefix") do
|
|
155
|
+
expect_no_offenses(<<~RUBY)
|
|
156
|
+
def apionly_serialize
|
|
157
|
+
CurrentUser.id
|
|
158
|
+
end
|
|
159
|
+
RUBY
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it("still registers an offense in a method not matching the prefix") do
|
|
163
|
+
expect_offense(<<~RUBY)
|
|
164
|
+
def process
|
|
165
|
+
CurrentUser.id
|
|
166
|
+
^^^^^^^^^^^^^^ `CurrentUser` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
167
|
+
end
|
|
168
|
+
RUBY
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
context("with IgnoredMethodSuffixes") do
|
|
173
|
+
let(:config) do
|
|
174
|
+
RuboCop::Config.new(
|
|
175
|
+
"YiffSpace/CurrentUserOutsideOfRequests" => {
|
|
176
|
+
"ClassName" => "CurrentUser",
|
|
177
|
+
"IgnoredMethods" => [],
|
|
178
|
+
"IgnoredMethodPrefixes" => [],
|
|
179
|
+
"IgnoredMethodSuffixes" => ["_current"],
|
|
180
|
+
"IgnoredMethodPatterns" => [],
|
|
181
|
+
},
|
|
182
|
+
)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it("does not register an offense in a method matching the suffix") do
|
|
186
|
+
expect_no_offenses(<<~RUBY)
|
|
187
|
+
def user_current
|
|
188
|
+
CurrentUser.id
|
|
189
|
+
end
|
|
190
|
+
RUBY
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
context("with IgnoredMethodPatterns") do
|
|
195
|
+
let(:config) do
|
|
196
|
+
RuboCop::Config.new(
|
|
197
|
+
"YiffSpace/CurrentUserOutsideOfRequests" => {
|
|
198
|
+
"ClassName" => "CurrentUser",
|
|
199
|
+
"IgnoredMethods" => [],
|
|
200
|
+
"IgnoredMethodPrefixes" => [],
|
|
201
|
+
"IgnoredMethodSuffixes" => [],
|
|
202
|
+
"IgnoredMethodPatterns" => ["^with_current_user"],
|
|
203
|
+
},
|
|
204
|
+
)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it("does not register an offense in a method matching the pattern") do
|
|
208
|
+
expect_no_offenses(<<~RUBY)
|
|
209
|
+
def with_current_user_context
|
|
210
|
+
CurrentUser.id
|
|
211
|
+
end
|
|
212
|
+
RUBY
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
context("with a namespaced ClassName (A::User)") do
|
|
217
|
+
let(:config) do
|
|
218
|
+
RuboCop::Config.new(
|
|
219
|
+
"YiffSpace/CurrentUserOutsideOfRequests" => {
|
|
220
|
+
"ClassName" => "A::User",
|
|
221
|
+
"IgnoredMethods" => [],
|
|
222
|
+
"IgnoredMethodPrefixes" => [],
|
|
223
|
+
"IgnoredMethodSuffixes" => [],
|
|
224
|
+
"IgnoredMethodPatterns" => [],
|
|
225
|
+
},
|
|
226
|
+
)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it("registers an offense for a bare User reference directly inside the A namespace") do
|
|
230
|
+
expect_offense(<<~RUBY)
|
|
231
|
+
module A
|
|
232
|
+
def self.user
|
|
233
|
+
User
|
|
234
|
+
^^^^ `A::User` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
RUBY
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it("registers an offense for User.method inside the A namespace") do
|
|
241
|
+
expect_offense(<<~RUBY)
|
|
242
|
+
module A
|
|
243
|
+
def self.user
|
|
244
|
+
User.id
|
|
245
|
+
^^^^^^^ `A::User` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
RUBY
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
it("registers an offense for a bare User reference in a nested module with no shadowing User") do
|
|
252
|
+
expect_offense(<<~RUBY)
|
|
253
|
+
module A
|
|
254
|
+
module B
|
|
255
|
+
def self.user
|
|
256
|
+
User
|
|
257
|
+
^^^^ `A::User` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
RUBY
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
it("does not register an offense for User in a module that defines its own User") do
|
|
265
|
+
expect_no_offenses(<<~RUBY)
|
|
266
|
+
module A
|
|
267
|
+
module C
|
|
268
|
+
class User; end
|
|
269
|
+
|
|
270
|
+
def self.user
|
|
271
|
+
User
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
RUBY
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it("does not register an offense for User outside the A namespace") do
|
|
279
|
+
expect_no_offenses(<<~RUBY)
|
|
280
|
+
def process
|
|
281
|
+
User.id
|
|
282
|
+
end
|
|
283
|
+
RUBY
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it("does not register an offense for User in an unrelated namespace") do
|
|
287
|
+
expect_no_offenses(<<~RUBY)
|
|
288
|
+
module B
|
|
289
|
+
def self.user
|
|
290
|
+
User.id
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
RUBY
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it("registers an offense for an absolute ::A::User reference even when a local User is in scope") do
|
|
297
|
+
expect_offense(<<~RUBY)
|
|
298
|
+
module A
|
|
299
|
+
module D
|
|
300
|
+
class User; end
|
|
301
|
+
|
|
302
|
+
def self.user
|
|
303
|
+
::A::User
|
|
304
|
+
^^^^^^^^^ `A::User` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
RUBY
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
context("with a deeply namespaced ClassName (A::Util::User)") do
|
|
313
|
+
let(:config) do
|
|
314
|
+
RuboCop::Config.new(
|
|
315
|
+
"YiffSpace/CurrentUserOutsideOfRequests" => {
|
|
316
|
+
"ClassName" => "A::Util::User",
|
|
317
|
+
"IgnoredMethods" => [],
|
|
318
|
+
"IgnoredMethodPrefixes" => [],
|
|
319
|
+
"IgnoredMethodSuffixes" => [],
|
|
320
|
+
"IgnoredMethodPatterns" => [],
|
|
321
|
+
},
|
|
322
|
+
)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
it("registers an offense for Util::User directly inside A") do
|
|
326
|
+
expect_offense(<<~RUBY)
|
|
327
|
+
module A
|
|
328
|
+
def self.user
|
|
329
|
+
Util::User
|
|
330
|
+
^^^^^^^^^^ `A::Util::User` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
RUBY
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
it("registers an offense for Util::User inside a nested module within A with no shadowing Util") do
|
|
337
|
+
expect_offense(<<~RUBY)
|
|
338
|
+
module A
|
|
339
|
+
module B
|
|
340
|
+
def self.user
|
|
341
|
+
Util::User
|
|
342
|
+
^^^^^^^^^^ `A::Util::User` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
RUBY
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
it("does not register an offense for Util::User outside the A namespace") do
|
|
350
|
+
expect_no_offenses(<<~RUBY)
|
|
351
|
+
def process
|
|
352
|
+
Util::User.id
|
|
353
|
+
end
|
|
354
|
+
RUBY
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
context("with a custom ClassName") do
|
|
359
|
+
let(:config) do
|
|
360
|
+
RuboCop::Config.new(
|
|
361
|
+
"YiffSpace/CurrentUserOutsideOfRequests" => {
|
|
362
|
+
"ClassName" => "RequestUser",
|
|
363
|
+
"IgnoredMethods" => [],
|
|
364
|
+
"IgnoredMethodPrefixes" => [],
|
|
365
|
+
"IgnoredMethodSuffixes" => [],
|
|
366
|
+
"IgnoredMethodPatterns" => [],
|
|
367
|
+
},
|
|
368
|
+
)
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
it("registers an offense for the configured class name") do
|
|
372
|
+
expect_offense(<<~RUBY)
|
|
373
|
+
def process
|
|
374
|
+
RequestUser.id
|
|
375
|
+
^^^^^^^^^^^^^^ `RequestUser` should only be used within the request cycle (controllers, views, helpers, decorators)
|
|
376
|
+
end
|
|
377
|
+
RUBY
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
it("does not register an offense for the default CurrentUser name") do
|
|
381
|
+
expect_no_offenses(<<~RUBY)
|
|
382
|
+
def process
|
|
383
|
+
CurrentUser.id
|
|
384
|
+
end
|
|
385
|
+
RUBY
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
it("does not register an offense inside the configured class definition") do
|
|
389
|
+
expect_no_offenses(<<~RUBY)
|
|
390
|
+
class RequestUser
|
|
391
|
+
def self.id
|
|
392
|
+
RequestStore[:current_user]&.id
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
RUBY
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe(RuboCop::Cop::YiffSpace::ResolvableUser, :config) do
|
|
4
|
+
let(:schema) { double("schema") }
|
|
5
|
+
let(:posts_table) { double("posts_table", name: "posts") }
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
allow(cop).to(receive(:schema).and_return(schema))
|
|
9
|
+
allow(schema).to(receive(:table_by).and_return(posts_table))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context("when only the _id column exists") do
|
|
13
|
+
before do
|
|
14
|
+
allow(posts_table).to(receive(:with_column?).with(name: "creator_id").and_return(true))
|
|
15
|
+
allow(posts_table).to(receive(:with_column?).with(name: "creator_ip_addr").and_return(false))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it("registers an offense and corrects to belongs_to_user") do
|
|
19
|
+
expect_offense(<<~RUBY)
|
|
20
|
+
class Post < ApplicationRecord
|
|
21
|
+
resolvable(:creator)
|
|
22
|
+
^^^^^^^^^^^^^^^^^^^^ use `belongs_to_user(:creator)` when `"creator_id"` column exists
|
|
23
|
+
end
|
|
24
|
+
RUBY
|
|
25
|
+
|
|
26
|
+
expect_correction(<<~RUBY)
|
|
27
|
+
class Post < ApplicationRecord
|
|
28
|
+
belongs_to_user(:creator)
|
|
29
|
+
end
|
|
30
|
+
RUBY
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context("when both the _id and _ip_addr columns exist") do
|
|
35
|
+
before do
|
|
36
|
+
allow(posts_table).to(receive(:with_column?).with(name: "creator_id").and_return(true))
|
|
37
|
+
allow(posts_table).to(receive(:with_column?).with(name: "creator_ip_addr").and_return(true))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it("registers an offense and corrects to belongs_to_user with ip: true") do
|
|
41
|
+
expect_offense(<<~RUBY)
|
|
42
|
+
class Post < ApplicationRecord
|
|
43
|
+
resolvable(:creator)
|
|
44
|
+
^^^^^^^^^^^^^^^^^^^^ use `belongs_to_user(:creator, ip: true)` when `"creator_id"` and `"creator_ip_addr"` columns exist
|
|
45
|
+
end
|
|
46
|
+
RUBY
|
|
47
|
+
|
|
48
|
+
expect_correction(<<~RUBY)
|
|
49
|
+
class Post < ApplicationRecord
|
|
50
|
+
belongs_to_user(:creator, ip: true)
|
|
51
|
+
end
|
|
52
|
+
RUBY
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context("when the _id column does not exist") do
|
|
57
|
+
before do
|
|
58
|
+
allow(posts_table).to(receive(:with_column?).with(name: "creator_id").and_return(false))
|
|
59
|
+
allow(posts_table).to(receive(:with_column?).with(name: "creator_ip_addr").and_return(false))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it("does not register an offense") do
|
|
63
|
+
expect_no_offenses(<<~RUBY)
|
|
64
|
+
class Post < ApplicationRecord
|
|
65
|
+
resolvable(:creator)
|
|
66
|
+
end
|
|
67
|
+
RUBY
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it("does not register an offense when the schema is unavailable") do
|
|
72
|
+
allow(cop).to(receive(:schema).and_return(nil))
|
|
73
|
+
|
|
74
|
+
expect_no_offenses(<<~RUBY)
|
|
75
|
+
class Post < ApplicationRecord
|
|
76
|
+
resolvable(:creator)
|
|
77
|
+
end
|
|
78
|
+
RUBY
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it("does not register an offense when the table is not found in the schema") do
|
|
82
|
+
allow(schema).to(receive(:table_by).and_return(nil))
|
|
83
|
+
|
|
84
|
+
expect_no_offenses(<<~RUBY)
|
|
85
|
+
class Post < ApplicationRecord
|
|
86
|
+
resolvable(:creator)
|
|
87
|
+
end
|
|
88
|
+
RUBY
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it("does not register an offense when the call is outside a class") do
|
|
92
|
+
allow(posts_table).to(receive(:with_column?).with(name: "creator_id").and_return(true))
|
|
93
|
+
allow(posts_table).to(receive(:with_column?).with(name: "creator_ip_addr").and_return(false))
|
|
94
|
+
|
|
95
|
+
expect_no_offenses(<<~RUBY)
|
|
96
|
+
resolvable(:creator)
|
|
97
|
+
RUBY
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.describe(RuboCop::Cop::YiffSpace::UserToId, :config) do
|
|
4
|
+
let(:config) { RuboCop::Config.new("YiffSpace/UserToId" => { "Enabled" => true }) }
|
|
5
|
+
|
|
6
|
+
it("registers an offense for the is_a?(User) ternary pattern and corrects it") do
|
|
7
|
+
expect_offense(<<~RUBY)
|
|
8
|
+
user.is_a?(User) ? user.id : user
|
|
9
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `u2id(user)` instead of `user.is_a?(User) ? user.id : user`
|
|
10
|
+
RUBY
|
|
11
|
+
|
|
12
|
+
expect_correction(<<~RUBY)
|
|
13
|
+
u2id(user)
|
|
14
|
+
RUBY
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it("registers an offense with a different variable name") do
|
|
18
|
+
expect_offense(<<~RUBY)
|
|
19
|
+
creator.is_a?(User) ? creator.id : creator
|
|
20
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `u2id(creator)` instead of `creator.is_a?(User) ? creator.id : creator`
|
|
21
|
+
RUBY
|
|
22
|
+
|
|
23
|
+
expect_correction(<<~RUBY)
|
|
24
|
+
u2id(creator)
|
|
25
|
+
RUBY
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it("does not register an offense when the if-branch receiver differs from the else-branch") do
|
|
29
|
+
expect_no_offenses(<<~RUBY)
|
|
30
|
+
user.is_a?(User) ? user.id : something_else
|
|
31
|
+
RUBY
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it("does not register an offense when checking against a non-User class") do
|
|
35
|
+
expect_no_offenses(<<~RUBY)
|
|
36
|
+
user.is_a?(Admin) ? user.id : user
|
|
37
|
+
RUBY
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it("does not register an offense when the if-branch does not call .id") do
|
|
41
|
+
expect_no_offenses(<<~RUBY)
|
|
42
|
+
user.is_a?(User) ? user.name : user
|
|
43
|
+
RUBY
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it("does not register an offense for a non-ternary if") do
|
|
47
|
+
expect_no_offenses(<<~RUBY)
|
|
48
|
+
if user.is_a?(User)
|
|
49
|
+
user.id
|
|
50
|
+
else
|
|
51
|
+
user
|
|
52
|
+
end
|
|
53
|
+
RUBY
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it("does not register an offense when already using u2id") do
|
|
57
|
+
expect_no_offenses(<<~RUBY)
|
|
58
|
+
u2id(user)
|
|
59
|
+
RUBY
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it("does not register an offense for unrelated ternaries") do
|
|
63
|
+
expect_no_offenses(<<~RUBY)
|
|
64
|
+
user.nil? ? nil : user
|
|
65
|
+
RUBY
|
|
66
|
+
end
|
|
67
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require("rubocop-yiffspace")
|
|
4
|
+
require("rubocop/rspec/support")
|
|
5
|
+
|
|
6
|
+
# Satisfy requires_gem("activerecord") checks in cops without loading the full gem.
|
|
7
|
+
Gem.loaded_specs["activerecord"] ||= Gem::Specification.new do |s|
|
|
8
|
+
s.name = "activerecord"
|
|
9
|
+
s.version = "8.0"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
RSpec.configure do |config|
|
|
13
|
+
config.disable_monkey_patching!
|
|
14
|
+
config.raise_errors_for_deprecations!
|
|
15
|
+
config.raise_on_warning = true
|
|
16
|
+
config.fail_if_no_examples = true
|
|
17
|
+
|
|
18
|
+
config.order = :random
|
|
19
|
+
Kernel.srand(config.seed)
|
|
20
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: rubocop-yiffspace
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Donovan_DMC
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-05-07 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: lint_roller
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.1'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.1'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rubocop
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 1.72.2
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 1.72.2
|
|
40
|
+
description: Shared rubocop rules for YiffSpace
|
|
41
|
+
email:
|
|
42
|
+
- hewwo@yiff.rocks
|
|
43
|
+
executables: []
|
|
44
|
+
extensions: []
|
|
45
|
+
extra_rdoc_files: []
|
|
46
|
+
files:
|
|
47
|
+
- ".idea/.gitignore"
|
|
48
|
+
- ".idea/jsonSchemas.xml"
|
|
49
|
+
- ".idea/misc.xml"
|
|
50
|
+
- ".idea/modules.xml"
|
|
51
|
+
- ".idea/rubocop-plugin.iml"
|
|
52
|
+
- ".idea/vcs.xml"
|
|
53
|
+
- ".rspec"
|
|
54
|
+
- ".ruby-version"
|
|
55
|
+
- LICENSE.txt
|
|
56
|
+
- README.md
|
|
57
|
+
- Rakefile
|
|
58
|
+
- config/custom.yml
|
|
59
|
+
- config/default.yml
|
|
60
|
+
- config/rails.yml
|
|
61
|
+
- config/shared.yml
|
|
62
|
+
- config/shared/bundler.yml
|
|
63
|
+
- config/shared/gemspec.yml
|
|
64
|
+
- config/shared/layout.yml
|
|
65
|
+
- config/shared/lint.yml
|
|
66
|
+
- config/shared/metrics.yml
|
|
67
|
+
- config/shared/migration.yml
|
|
68
|
+
- config/shared/naming.yml
|
|
69
|
+
- config/shared/rails.yml
|
|
70
|
+
- config/shared/security.yml
|
|
71
|
+
- config/shared/style.yml
|
|
72
|
+
- lib/rubocop-yiffspace.rb
|
|
73
|
+
- lib/rubocop/cop/mixin/active_record_helper.rb
|
|
74
|
+
- lib/rubocop/cop/mixin/node_formatting_helper.rb
|
|
75
|
+
- lib/rubocop/cop/yiff_space/belongs_to_user.rb
|
|
76
|
+
- lib/rubocop/cop/yiff_space/belongs_to_user_invalid_ip.rb
|
|
77
|
+
- lib/rubocop/cop/yiff_space/belongs_to_user_missing_ip.rb
|
|
78
|
+
- lib/rubocop/cop/yiff_space/current_user_outside_of_requests.rb
|
|
79
|
+
- lib/rubocop/cop/yiff_space/resolvable_user.rb
|
|
80
|
+
- lib/rubocop/cop/yiff_space/user_to_id.rb
|
|
81
|
+
- lib/rubocop/cop/yiffspace_cops.rb
|
|
82
|
+
- lib/rubocop/yiff_space.rb
|
|
83
|
+
- lib/rubocop/yiff_space/plugin.rb
|
|
84
|
+
- lib/rubocop/yiff_space/version.rb
|
|
85
|
+
- spec/rubocop/cop/yiff_space/belongs_to_user_invalid_ip_spec.rb
|
|
86
|
+
- spec/rubocop/cop/yiff_space/belongs_to_user_missing_ip_spec.rb
|
|
87
|
+
- spec/rubocop/cop/yiff_space/belongs_to_user_spec.rb
|
|
88
|
+
- spec/rubocop/cop/yiff_space/current_user_outside_of_requests_spec.rb
|
|
89
|
+
- spec/rubocop/cop/yiff_space/resolvable_user_spec.rb
|
|
90
|
+
- spec/rubocop/cop/yiff_space/user_to_id_spec.rb
|
|
91
|
+
- spec/spec_helper.rb
|
|
92
|
+
homepage: https://github.com/YiffSpace/rubocop-plugin
|
|
93
|
+
licenses:
|
|
94
|
+
- MIT
|
|
95
|
+
metadata:
|
|
96
|
+
allowed_push_host: https://rubygems.org
|
|
97
|
+
homepage_uri: https://github.com/YiffSpace/rubocop-plugin
|
|
98
|
+
source_code_uri: https://github.com/YiffSpace/rubocop-plugin
|
|
99
|
+
rubygems_mfa_required: 'true'
|
|
100
|
+
default_lint_roller_plugin: RuboCop::YiffSpace::Plugin
|
|
101
|
+
rdoc_options: []
|
|
102
|
+
require_paths:
|
|
103
|
+
- lib
|
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
105
|
+
requirements:
|
|
106
|
+
- - ">="
|
|
107
|
+
- !ruby/object:Gem::Version
|
|
108
|
+
version: 3.4.1
|
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
|
+
requirements:
|
|
111
|
+
- - ">="
|
|
112
|
+
- !ruby/object:Gem::Version
|
|
113
|
+
version: '0'
|
|
114
|
+
requirements: []
|
|
115
|
+
rubygems_version: 3.6.2
|
|
116
|
+
specification_version: 4
|
|
117
|
+
summary: Shared rubocop rules for YiffSpace
|
|
118
|
+
test_files: []
|