rubocop-rails 2.6.0 → 2.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -0
  3. data/config/default.yml +189 -6
  4. data/lib/rubocop/cop/mixin/active_record_helper.rb +12 -3
  5. data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
  6. data/lib/rubocop/cop/mixin/index_method.rb +25 -11
  7. data/lib/rubocop/cop/rails/action_filter.rb +10 -14
  8. data/lib/rubocop/cop/rails/active_record_aliases.rb +13 -17
  9. data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +148 -0
  10. data/lib/rubocop/cop/rails/active_record_override.rb +1 -1
  11. data/lib/rubocop/cop/rails/active_support_aliases.rb +12 -21
  12. data/lib/rubocop/cop/rails/after_commit_override.rb +91 -0
  13. data/lib/rubocop/cop/rails/application_controller.rb +3 -7
  14. data/lib/rubocop/cop/rails/application_job.rb +2 -1
  15. data/lib/rubocop/cop/rails/application_mailer.rb +2 -7
  16. data/lib/rubocop/cop/rails/application_record.rb +2 -7
  17. data/lib/rubocop/cop/rails/arel_star.rb +41 -0
  18. data/lib/rubocop/cop/rails/assert_not.rb +8 -10
  19. data/lib/rubocop/cop/rails/attribute_default_block_value.rb +90 -0
  20. data/lib/rubocop/cop/rails/belongs_to.rb +9 -18
  21. data/lib/rubocop/cop/rails/blank.rb +27 -27
  22. data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
  23. data/lib/rubocop/cop/rails/content_tag.rb +20 -33
  24. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -1
  25. data/lib/rubocop/cop/rails/date.rb +10 -11
  26. data/lib/rubocop/cop/rails/default_scope.rb +61 -0
  27. data/lib/rubocop/cop/rails/delegate.rb +10 -10
  28. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
  29. data/lib/rubocop/cop/rails/dynamic_find_by.rb +13 -11
  30. data/lib/rubocop/cop/rails/enum_hash.rb +11 -10
  31. data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -1
  32. data/lib/rubocop/cop/rails/environment_comparison.rb +18 -14
  33. data/lib/rubocop/cop/rails/exit.rb +4 -10
  34. data/lib/rubocop/cop/rails/file_path.rb +5 -4
  35. data/lib/rubocop/cop/rails/find_by.rb +13 -13
  36. data/lib/rubocop/cop/rails/find_by_id.rb +94 -0
  37. data/lib/rubocop/cop/rails/find_each.rb +16 -14
  38. data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
  39. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +4 -7
  40. data/lib/rubocop/cop/rails/helper_instance_variable.rb +4 -2
  41. data/lib/rubocop/cop/rails/http_positional_arguments.rb +25 -21
  42. data/lib/rubocop/cop/rails/http_status.rb +7 -9
  43. data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +8 -6
  44. data/lib/rubocop/cop/rails/index_by.rb +11 -2
  45. data/lib/rubocop/cop/rails/index_with.rb +11 -2
  46. data/lib/rubocop/cop/rails/inquiry.rb +39 -0
  47. data/lib/rubocop/cop/rails/inverse_of.rb +3 -2
  48. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -15
  49. data/lib/rubocop/cop/rails/link_to_blank.rb +20 -20
  50. data/lib/rubocop/cop/rails/mailer_name.rb +86 -0
  51. data/lib/rubocop/cop/rails/match_route.rb +120 -0
  52. data/lib/rubocop/cop/rails/negate_include.rb +41 -0
  53. data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
  54. data/lib/rubocop/cop/rails/order_by_id.rb +52 -0
  55. data/lib/rubocop/cop/rails/output.rb +5 -2
  56. data/lib/rubocop/cop/rails/output_safety.rb +3 -2
  57. data/lib/rubocop/cop/rails/pick.rb +21 -15
  58. data/lib/rubocop/cop/rails/pluck.rb +56 -0
  59. data/lib/rubocop/cop/rails/pluck_id.rb +56 -0
  60. data/lib/rubocop/cop/rails/pluck_in_where.rb +70 -0
  61. data/lib/rubocop/cop/rails/pluralization_grammar.rb +10 -14
  62. data/lib/rubocop/cop/rails/presence.rb +12 -13
  63. data/lib/rubocop/cop/rails/present.rb +30 -24
  64. data/lib/rubocop/cop/rails/rake_environment.rb +9 -11
  65. data/lib/rubocop/cop/rails/read_write_attribute.rb +12 -11
  66. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +29 -31
  67. data/lib/rubocop/cop/rails/redundant_foreign_key.rb +9 -12
  68. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +11 -10
  69. data/lib/rubocop/cop/rails/reflection_class_name.rb +4 -3
  70. data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
  71. data/lib/rubocop/cop/rails/relative_date_constant.rb +20 -9
  72. data/lib/rubocop/cop/rails/render_inline.rb +41 -0
  73. data/lib/rubocop/cop/rails/render_plain_text.rb +71 -0
  74. data/lib/rubocop/cop/rails/request_referer.rb +7 -7
  75. data/lib/rubocop/cop/rails/reversible_migration.rb +82 -7
  76. data/lib/rubocop/cop/rails/safe_navigation.rb +12 -11
  77. data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
  78. data/lib/rubocop/cop/rails/save_bang.rb +19 -22
  79. data/lib/rubocop/cop/rails/scope_args.rb +2 -1
  80. data/lib/rubocop/cop/rails/short_i18n.rb +74 -0
  81. data/lib/rubocop/cop/rails/skips_model_validations.rb +46 -11
  82. data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +82 -0
  83. data/lib/rubocop/cop/rails/time_zone.rb +22 -20
  84. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +10 -10
  85. data/lib/rubocop/cop/rails/unique_validation_without_index.rb +18 -8
  86. data/lib/rubocop/cop/rails/unknown_env.rb +15 -4
  87. data/lib/rubocop/cop/rails/validation.rb +15 -14
  88. data/lib/rubocop/cop/rails/where_equals.rb +94 -0
  89. data/lib/rubocop/cop/rails/where_exists.rb +126 -0
  90. data/lib/rubocop/cop/rails/where_not.rb +97 -0
  91. data/lib/rubocop/cop/rails_cops.rb +22 -0
  92. data/lib/rubocop/rails/schema_loader.rb +4 -4
  93. data/lib/rubocop/rails/schema_loader/schema.rb +5 -5
  94. data/lib/rubocop/rails/version.rb +5 -1
  95. metadata +37 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6b55ee8df864d6eaee4a491f4324343ee2274eafcb352952a81ff045832aa22
4
- data.tar.gz: 344ea324a589dc25ce3e87366c4af33bde4e392acf6acaccf9b9296066680824
3
+ metadata.gz: b997fb5d9995a5c7db5d151e13b86cf0dbd2b27f890e9ad116d11fab30a1b7e0
4
+ data.tar.gz: 91c6b0a496bcbe9c92b0833944b301e893c9f9ee6e75db0fb393436c9869dc81
5
5
  SHA512:
6
- metadata.gz: 5bdccc2a5e2a45533cb5bb33b2df26872f806dd590c13d640d7449315e56ec6250aebdb876fb37812bb3dd47cdaeda61c6049bc5cf98b01b473a616e9061491b
7
- data.tar.gz: 6f8673f2e8d0068bcdbe1599936793461bab38f4b333a4ac6e22e03e7162851d6fc20543ec58e3f2fabdf404764b09f8ff47e6a5c23d492f0c8bb28acd012296
6
+ metadata.gz: d59f7cbb8d1f311bcdda8eda6c1c55d5cbc772993cac726f6d16d1947ca324b95354e24770140d3fce1a860cd2b4995d55c78e946c21ed85c9f4964b4d908794
7
+ data.tar.gz: 891fc8896d26423f80edd9db48e75c065c3e46ccb03a534f182dd3af928b19165e7d2d259cd842b1222a729ba4e234d461e370327db4bb520673ab61071e0e89
data/README.md CHANGED
@@ -86,6 +86,22 @@ Rails cops support the following versions:
86
86
 
87
87
  - Rails 4.2+
88
88
 
89
+ ## Readme Badge
90
+
91
+ If you use RuboCop Rails in your project, you can include one of these badges in your readme to let people know that your code is written following the community Rails Style Guide.
92
+
93
+ [![Rails Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop-hq/rubocop-rails)
94
+
95
+ [![Rails Style Guide](https://img.shields.io/badge/code_style-community-brightgreen.svg)](https://rails.rubystyle.guide)
96
+
97
+ Here are the Markdown snippets for the two badges:
98
+
99
+ ``` markdown
100
+ [![Rails Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop-hq/rubocop-rails)
101
+
102
+ [![Rails Style Guide](https://img.shields.io/badge/code_style-community-brightgreen.svg)](https://rails.rubystyle.guide)
103
+ ```
104
+
89
105
  ## Contributing
90
106
 
91
107
  Checkout the [contribution guidelines](CONTRIBUTING.md).
@@ -37,6 +37,14 @@ Rails/ActiveRecordAliases:
37
37
  VersionAdded: '0.53'
38
38
  SafeAutoCorrect: false
39
39
 
40
+ Rails/ActiveRecordCallbacksOrder:
41
+ Description: 'Order callback declarations in the order in which they will be executed.'
42
+ StyleGuide: 'https://rails.rubystyle.guide/#callbacks-order'
43
+ Enabled: 'pending'
44
+ VersionAdded: '2.7'
45
+ Include:
46
+ - app/models/**/*.rb
47
+
40
48
  Rails/ActiveRecordOverride:
41
49
  Description: >-
42
50
  Check for overriding Active Record methods instead of using
@@ -54,6 +62,14 @@ Rails/ActiveSupportAliases:
54
62
  Enabled: true
55
63
  VersionAdded: '0.48'
56
64
 
65
+ Rails/AfterCommitOverride:
66
+ Description: >-
67
+ This cop enforces that there is only one call to `after_commit`
68
+ (and its aliases - `after_create_commit`, `after_update_commit`,
69
+ and `after_destroy_commit`) with the same callback name per model.
70
+ Enabled: 'pending'
71
+ VersionAdded: '2.8'
72
+
57
73
  Rails/ApplicationController:
58
74
  Description: 'Check that controllers subclass ApplicationController.'
59
75
  Enabled: true
@@ -82,6 +98,12 @@ Rails/ApplicationRecord:
82
98
  VersionAdded: '0.49'
83
99
  VersionChanged: '2.5'
84
100
 
101
+ Rails/ArelStar:
102
+ Description: 'Enforces `Arel.star` instead of `"*"` for expanded columns.'
103
+ Enabled: true
104
+ SafeAutoCorrect: false
105
+ VersionAdded: '2.9'
106
+
85
107
  Rails/AssertNot:
86
108
  Description: 'Use `assert_not` instead of `assert !`.'
87
109
  Enabled: true
@@ -89,6 +111,13 @@ Rails/AssertNot:
89
111
  Include:
90
112
  - '**/test/**/*'
91
113
 
114
+ Rails/AttributeDefaultBlockValue:
115
+ Description: 'Pass method call in block for attribute option `default`.'
116
+ Enabled: pending
117
+ VersionAdded: '2.9'
118
+ Include:
119
+ - 'models/**/*'
120
+
92
121
  Rails/BelongsTo:
93
122
  Description: >-
94
123
  Use `optional: true` instead of `required: false` for
@@ -153,6 +182,12 @@ Rails/Date:
153
182
  - strict
154
183
  - flexible
155
184
 
185
+ Rails/DefaultScope:
186
+ Description: 'Avoid use of `default_scope`.'
187
+ StyleGuide: 'https://rails.rubystyle.guide#avoid-default-scope'
188
+ Enabled: false
189
+ VersionAdded: '2.7'
190
+
156
191
  Rails/Delegate:
157
192
  Description: 'Prefer delegate method for delegations.'
158
193
  Enabled: true
@@ -234,13 +269,28 @@ Rails/FindBy:
234
269
  Include:
235
270
  - app/models/**/*.rb
236
271
 
272
+ Rails/FindById:
273
+ Description: >-
274
+ Favor the use of `find` over `where.take!`, `find_by!`, and `find_by_id!` when you
275
+ need to retrieve a single record by primary key when you expect it to be found.
276
+ StyleGuide: 'https://rails.rubystyle.guide/#find'
277
+ Enabled: 'pending'
278
+ VersionAdded: '2.7'
279
+
237
280
  Rails/FindEach:
238
281
  Description: 'Prefer all.find_each over all.find.'
239
282
  StyleGuide: 'https://rails.rubystyle.guide#find-each'
240
283
  Enabled: true
241
284
  VersionAdded: '0.30'
285
+ VersionChanged: '2.9'
242
286
  Include:
243
287
  - app/models/**/*.rb
288
+ IgnoredMethods:
289
+ # Methods that don't work well with `find_each`.
290
+ - order
291
+ - limit
292
+ - select
293
+ - lock
244
294
 
245
295
  Rails/HasAndBelongsToMany:
246
296
  Description: 'Prefer has_many :through to has_and_belongs_to_many.'
@@ -291,14 +341,22 @@ Rails/IgnoredSkipActionFilterOption:
291
341
  - app/controllers/**/*.rb
292
342
 
293
343
  Rails/IndexBy:
294
- Description: 'Prefer `index_by` over `each_with_object` or `map`.'
344
+ Description: 'Prefer `index_by` over `each_with_object`, `to_h`, or `map`.'
295
345
  Enabled: true
296
346
  VersionAdded: '2.5'
347
+ VersionChanged: '2.8'
297
348
 
298
349
  Rails/IndexWith:
299
- Description: 'Prefer `index_with` over `each_with_object` or `map`.'
350
+ Description: 'Prefer `index_with` over `each_with_object`, `to_h`, or `map`.'
300
351
  Enabled: true
301
352
  VersionAdded: '2.5'
353
+ VersionChanged: '2.8'
354
+
355
+ Rails/Inquiry:
356
+ Description: "Prefer Ruby's comparison operators over Active Support's `Array#inquiry` and `String#inquiry`."
357
+ StyleGuide: 'https://rails.rubystyle.guide/#inquiry'
358
+ Enabled: 'pending'
359
+ VersionAdded: '2.7'
302
360
 
303
361
  Rails/InverseOf:
304
362
  Description: 'Checks for associations where the inverse cannot be determined automatically.'
@@ -325,6 +383,34 @@ Rails/LinkToBlank:
325
383
  Enabled: true
326
384
  VersionAdded: '0.62'
327
385
 
386
+ Rails/MailerName:
387
+ Description: 'Mailer should end with `Mailer` suffix.'
388
+ StyleGuide: 'https://rails.rubystyle.guide/#mailer-name'
389
+ Enabled: 'pending'
390
+ SafeAutoCorrect: false
391
+ VersionAdded: '2.7'
392
+ Include:
393
+ - app/mailers/**/*.rb
394
+
395
+ Rails/MatchRoute:
396
+ Description: >-
397
+ Don't use `match` to define any routes unless there is a need to map multiple request types
398
+ among [:get, :post, :patch, :put, :delete] to a single action using the `:via` option.
399
+ StyleGuide: 'https://rails.rubystyle.guide/#no-match-routes'
400
+ Enabled: 'pending'
401
+ VersionAdded: '2.7'
402
+ Include:
403
+ - config/routes.rb
404
+ - config/routes/**/*.rb
405
+
406
+ Rails/NegateInclude:
407
+ Description: 'Prefer `collection.exclude?(obj)` over `!collection.include?(obj)`.'
408
+ StyleGuide: 'https://rails.rubystyle.guide#exclude'
409
+ Enabled: 'pending'
410
+ Safe: false
411
+ VersionAdded: '2.7'
412
+ VersionChanged: '2.9'
413
+
328
414
  Rails/NotNullColumn:
329
415
  Description: 'Do not add a NOT NULL column without a default value.'
330
416
  Enabled: true
@@ -332,6 +418,14 @@ Rails/NotNullColumn:
332
418
  Include:
333
419
  - db/migrate/*.rb
334
420
 
421
+ Rails/OrderById:
422
+ Description: >-
423
+ Do not use the `id` column for ordering.
424
+ Use a timestamp column to order chronologically.
425
+ StyleGuide: 'https://rails.rubystyle.guide/#order-by-id'
426
+ Enabled: false
427
+ VersionAdded: '2.8'
428
+
335
429
  Rails/Output:
336
430
  Description: 'Checks for calls to puts, print, etc.'
337
431
  Enabled: true
@@ -350,10 +444,35 @@ Rails/OutputSafety:
350
444
 
351
445
  Rails/Pick:
352
446
  Description: 'Prefer `pick` over `pluck(...).first`.'
447
+ StyleGuide: 'https://rails.rubystyle.guide#pick'
353
448
  Enabled: true
354
449
  Safe: false
355
450
  VersionAdded: '2.6'
356
451
 
452
+ Rails/Pluck:
453
+ Description: 'Prefer `pluck` over `map { ... }`.'
454
+ StyleGuide: 'https://rails.rubystyle.guide#pluck'
455
+ Enabled: 'pending'
456
+ VersionAdded: '2.7'
457
+
458
+ Rails/PluckId:
459
+ Description: 'Use `ids` instead of `pluck(:id)` or `pluck(primary_key)`.'
460
+ StyleGuide: 'https://rails.rubystyle.guide/#ids'
461
+ Enabled: false
462
+ Safe: false
463
+ VersionAdded: '2.7'
464
+
465
+ Rails/PluckInWhere:
466
+ Description: 'Use `select` instead of `pluck` in `where` query methods.'
467
+ Enabled: 'pending'
468
+ Safe: false
469
+ VersionAdded: '2.7'
470
+ VersionChanged: '2.8'
471
+ EnforcedStyle: conservative
472
+ SupportedStyles:
473
+ - conservative
474
+ - aggressive
475
+
357
476
  Rails/PluralizationGrammar:
358
477
  Description: 'Checks for incorrect grammar when using methods like `3.day.ago`.'
359
478
  Enabled: true
@@ -441,6 +560,20 @@ Rails/RelativeDateConstant:
441
560
  VersionChanged: '0.59'
442
561
  AutoCorrect: false
443
562
 
563
+ Rails/RenderInline:
564
+ Description: 'Prefer using a template over inline rendering.'
565
+ StyleGuide: 'https://rails.rubystyle.guide/#inline-rendering'
566
+ Enabled: 'pending'
567
+ VersionAdded: '2.7'
568
+
569
+ Rails/RenderPlainText:
570
+ Description: 'Prefer `render plain:` over `render text:`.'
571
+ StyleGuide: 'https://rails.rubystyle.guide/#plain-text-rendering'
572
+ Enabled: 'pending'
573
+ VersionAdded: '2.7'
574
+ # Convert only when `content_type` is explicitly set to `text/plain`.
575
+ ContentTypeCompatibility: true
576
+
444
577
  Rails/RequestReferer:
445
578
  Description: 'Use consistent syntax for request.referer.'
446
579
  Enabled: true
@@ -498,6 +631,16 @@ Rails/ScopeArgs:
498
631
  Include:
499
632
  - app/models/**/*.rb
500
633
 
634
+ Rails/ShortI18n:
635
+ Description: 'Use the short form of the I18n methods: `t` instead of `translate` and `l` instead of `localize`.'
636
+ StyleGuide: 'https://rails.rubystyle.guide/#short-i18n'
637
+ Enabled: 'pending'
638
+ VersionAdded: '2.7'
639
+ EnforcedStyle: conservative
640
+ SupportedStyles:
641
+ - conservative
642
+ - aggressive
643
+
501
644
  Rails/SkipsModelValidations:
502
645
  Description: >-
503
646
  Use methods that skips model validations with caution.
@@ -505,20 +648,37 @@ Rails/SkipsModelValidations:
505
648
  Reference: 'https://guides.rubyonrails.org/active_record_validations.html#skipping-validations'
506
649
  Enabled: true
507
650
  VersionAdded: '0.47'
508
- VersionChanged: '0.60'
509
- Blacklist:
651
+ VersionChanged: '2.7'
652
+ ForbiddenMethods:
510
653
  - decrement!
511
654
  - decrement_counter
512
655
  - increment!
513
656
  - increment_counter
657
+ - insert
658
+ - insert!
659
+ - insert_all
660
+ - insert_all!
514
661
  - toggle!
515
662
  - touch
663
+ - touch_all
516
664
  - update_all
517
665
  - update_attribute
518
666
  - update_column
519
667
  - update_columns
520
668
  - update_counters
521
- Whitelist: []
669
+ - upsert
670
+ - upsert_all
671
+ AllowedMethods: []
672
+
673
+ Rails/SquishedSQLHeredocs:
674
+ Description: 'Checks SQL heredocs to use `.squish`.'
675
+ StyleGuide: 'https://rails.rubystyle.guide/#squished-heredocs'
676
+ Enabled: 'pending'
677
+ VersionAdded: '2.8'
678
+ VersionChanged: '2.9'
679
+ # Some SQL syntax (e.g. PostgreSQL comments and functions) requires newlines
680
+ # to be preserved in order to work, thus auto-correction is not safe.
681
+ SafeAutoCorrect: false
522
682
 
523
683
  Rails/TimeZone:
524
684
  Description: 'Checks the correct usage of time zone aware methods.'
@@ -539,11 +699,12 @@ Rails/UniqBeforePluck:
539
699
  Description: 'Prefer the use of uniq or distinct before pluck.'
540
700
  Enabled: true
541
701
  VersionAdded: '0.40'
542
- VersionChanged: '2.6'
702
+ VersionChanged: '2.8'
543
703
  EnforcedStyle: conservative
544
704
  SupportedStyles:
545
705
  - conservative
546
706
  - aggressive
707
+ SafeAutoCorrect: false
547
708
  AutoCorrect: false
548
709
 
549
710
  Rails/UniqueValidationWithoutIndex:
@@ -570,6 +731,28 @@ Rails/Validation:
570
731
  Include:
571
732
  - app/models/**/*.rb
572
733
 
734
+ Rails/WhereEquals:
735
+ Description: 'Pass conditions to `where` as a hash instead of manually constructing SQL.'
736
+ StyleGuide: 'https://rails.rubystyle.guide/#hash-conditions'
737
+ Enabled: 'pending'
738
+ VersionAdded: '2.9'
739
+
740
+ Rails/WhereExists:
741
+ Description: 'Prefer `exists?(...)` over `where(...).exists?`.'
742
+ Enabled: 'pending'
743
+ EnforcedStyle: exists
744
+ SupportedStyles:
745
+ - exists
746
+ - where
747
+ VersionAdded: '2.7'
748
+ VersionChanged: '2.8'
749
+
750
+ Rails/WhereNot:
751
+ Description: 'Use `where.not(...)` instead of manually constructing negated SQL in `where`.'
752
+ StyleGuide: 'https://rails.rubystyle.guide/#hash-conditions'
753
+ Enabled: 'pending'
754
+ VersionAdded: '2.8'
755
+
573
756
  # Accept `redirect_to(...) and return` and similar cases.
574
757
  Style/AndOr:
575
758
  EnforcedStyle: conditionals
@@ -6,6 +6,8 @@ module RuboCop
6
6
  module ActiveRecordHelper
7
7
  extend NodePattern::Macros
8
8
 
9
+ WHERE_METHODS = %i[where rewhere].freeze
10
+
9
11
  def_node_search :find_set_table_name, <<~PATTERN
10
12
  (send self :table_name= {str sym})
11
13
  PATTERN
@@ -33,10 +35,11 @@ module RuboCop
33
35
  table_name = find_set_table_name(class_node).to_a.last&.first_argument
34
36
  return table_name.value.to_s if table_name
35
37
 
36
- namespaces = class_node.each_ancestor(:class, :module)
37
- [class_node, *namespaces]
38
+ class_nodes = class_node.defined_module.each_node
39
+ namespaces = class_node.each_ancestor(:class, :module).map(&:identifier)
40
+ [*class_nodes, *namespaces]
38
41
  .reverse
39
- .map { |klass| klass.identifier.children[1] }.join('_')
42
+ .map { |node| node.children[1] }.join('_')
40
43
  .tableize
41
44
  end
42
45
 
@@ -50,6 +53,7 @@ module RuboCop
50
53
  # @param table [RuboCop::Rails::SchemaLoader::Table]
51
54
  # @return [String, nil]
52
55
  def resolve_relation_into_column(name:, class_node:, table:)
56
+ return unless table
53
57
  return name if table.with_column?(name: name)
54
58
 
55
59
  find_belongs_to(class_node) do |belongs_to|
@@ -72,6 +76,11 @@ module RuboCop
72
76
  break pair.value.value.to_s
73
77
  end
74
78
  end
79
+
80
+ def in_where?(node)
81
+ send_node = node.each_ancestor(:send).first
82
+ send_node && WHERE_METHODS.include?(send_node.method_name)
83
+ end
75
84
  end
76
85
  end
77
86
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Common functionality for enforcing a specific superclass.
6
+ module EnforceSuperclass
7
+ def self.included(base)
8
+ base.def_node_matcher :class_definition, <<~PATTERN
9
+ (class (const _ !:#{base::SUPERCLASS}) #{base::BASE_PATTERN} ...)
10
+ PATTERN
11
+
12
+ base.def_node_matcher :class_new_definition, <<~PATTERN
13
+ [!^(casgn {nil? cbase} :#{base::SUPERCLASS} ...)
14
+ !^^(casgn {nil? cbase} :#{base::SUPERCLASS} (block ...))
15
+ (send (const {nil? cbase} :Class) :new #{base::BASE_PATTERN})]
16
+ PATTERN
17
+ end
18
+
19
+ def on_class(node)
20
+ class_definition(node) do
21
+ register_offense(node.children[1])
22
+ end
23
+ end
24
+
25
+ def on_send(node)
26
+ class_new_definition(node) do
27
+ register_offense(node.children.last)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def register_offense(offense_node)
34
+ add_offense(offense_node) do |corrector|
35
+ corrector.replace(offense_node.source_range, self.class::SUPERCLASS)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -4,10 +4,18 @@ module RuboCop
4
4
  module Cop
5
5
  # Common functionality for Rails/IndexBy and Rails/IndexWith
6
6
  module IndexMethod # rubocop:disable Metrics/ModuleLength
7
+ RESTRICT_ON_SEND = %i[each_with_object to_h map collect []].freeze
8
+
7
9
  def on_block(node)
8
10
  on_bad_each_with_object(node) do |*match|
9
11
  handle_possible_offense(node, match, 'each_with_object')
10
12
  end
13
+
14
+ return if target_ruby_version < 2.6
15
+
16
+ on_bad_to_h(node) do |*match|
17
+ handle_possible_offense(node, match, 'to_h { ... }')
18
+ end
11
19
  end
12
20
 
13
21
  def on_send(node)
@@ -26,13 +34,6 @@ module RuboCop
26
34
  end
27
35
  end
28
36
 
29
- def autocorrect(node)
30
- lambda do |corrector|
31
- correction = prepare_correction(node)
32
- execute_correction(corrector, node, correction)
33
- end
34
- end
35
-
36
37
  private
37
38
 
38
39
  # @abstract Implemented with `def_node_matcher`
@@ -40,6 +41,11 @@ module RuboCop
40
41
  raise NotImplementedError
41
42
  end
42
43
 
44
+ # @abstract Implemented with `def_node_matcher`
45
+ def on_bad_to_h(_node)
46
+ raise NotImplementedError
47
+ end
48
+
43
49
  # @abstract Implemented with `def_node_matcher`
44
50
  def on_bad_map_to_h(_node)
45
51
  raise NotImplementedError
@@ -56,9 +62,11 @@ module RuboCop
56
62
  return if captures.noop_transformation?
57
63
 
58
64
  add_offense(
59
- node,
60
- message: "Prefer `#{new_method_name}` over `#{match_desc}`."
61
- )
65
+ node, message: "Prefer `#{new_method_name}` over `#{match_desc}`."
66
+ ) do |corrector|
67
+ correction = prepare_correction(node)
68
+ execute_correction(corrector, node, correction)
69
+ end
62
70
  end
63
71
 
64
72
  def extract_captures(match)
@@ -73,6 +81,8 @@ module RuboCop
73
81
  def prepare_correction(node)
74
82
  if (match = on_bad_each_with_object(node))
75
83
  Autocorrection.from_each_with_object(node, match)
84
+ elsif (match = on_bad_to_h(node))
85
+ Autocorrection.from_to_h(node, match)
76
86
  elsif (match = on_bad_map_to_h(node))
77
87
  Autocorrection.from_map_to_h(node, match)
78
88
  elsif (match = on_bad_hash_brackets_map(node))
@@ -106,11 +116,15 @@ module RuboCop
106
116
  end
107
117
 
108
118
  # Internal helper class to hold autocorrect data
109
- Autocorrection = Struct.new(:match, :block_node, :leading, :trailing) do # rubocop:disable Metrics/BlockLength
119
+ Autocorrection = Struct.new(:match, :block_node, :leading, :trailing) do
110
120
  def self.from_each_with_object(node, match)
111
121
  new(match, node, 0, 0)
112
122
  end
113
123
 
124
+ def self.from_to_h(node, match)
125
+ new(match, node, 0, 0)
126
+ end
127
+
114
128
  def self.from_map_to_h(node, match)
115
129
  strip_trailing_chars = 0
116
130