betterlint 1.29.0 → 1.31.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4be70714f121b7f33abf6c01f95ff109af80785e27d242225d3e4b0dcf3baa2a
4
- data.tar.gz: 233a10f1796cd42ebdebfa2ef715d7252f9d30abc6498e4f5cb5cec57b3f28a9
3
+ metadata.gz: df6ab37fcacbca2232240ecc261718b03ce8cae9d9ec6860d01b1fe5aafa15de
4
+ data.tar.gz: 3c1aace8b60b77b649f621b5923f3defddb33d18922aff23211225cea7461af5
5
5
  SHA512:
6
- metadata.gz: 7eebfe8e66e6098b8f78a2c5e564b51500bbbb5391f7fb341558495b0a8a8e3124f11be94a0d25ea7a3648a56c7d945d8f39815bdc30d28b8aff5374a7b768f2
7
- data.tar.gz: d3f7249277cc5268cd7b6182fd4a21f98cf9e8150c6544a10af4476b879bded4675a9851b8b7f9faf541cc1863de573e6c4d6ef4969e8382338fd78620b3a08b
6
+ metadata.gz: 0405efeb7e9268e65ab0440399f375e482338b7008a9ffa4690cbdc0640d8f0d1e5ea5382ddf2f203f54beb517f76387386f104b0f2a20519615e9c34f3bd6fd
7
+ data.tar.gz: 668fba99358e61376714517009c13e3e335e74c5576541941293c56018a851dca599edb0333160d99c27a31b192ec730149dac7cdf53045dbbac2cc24f643fba
data/README.md CHANGED
@@ -19,6 +19,10 @@ plugins:
19
19
  - betterlint
20
20
  ```
21
21
 
22
+ ## Upgrading to 1.30
23
+
24
+ Migration files are included in normal lint runs. Set `AllCops/MigratedSchemaVersion` to the last existing migration version to [skip historical files](#bettermentnodownmigrations).
25
+
22
26
  ## Dependencies
23
27
 
24
28
  This gem depends on the following other gems:
@@ -235,6 +239,49 @@ Betterment/UnsafeJob:
235
239
 
236
240
  It may make sense to consult your application's values for `Rails.application.config.filter_parameters`; if the application is filtering specific parameters from being logged, it might be a good idea to prevent these values from being stored in plaintext in a database as well.
237
241
 
242
+ ### Betterment/NoDownMigrations
243
+
244
+ This cop enforces [the rule against down migrations](https://the-book.betterment.io/rules/ruby/#do-not-write-down-migrations)
245
+ by flagging `down` methods and `direction.down` calls in migration `reversible` blocks.
246
+ It allows `change` and standalone `up` methods and does not autocorrect.
247
+
248
+ **Bad**
249
+
250
+ ```ruby
251
+ class AddNickname < ActiveRecord::Migration[8.0]
252
+ def up
253
+ add_column :users, :nickname, :string
254
+ end
255
+
256
+ def down
257
+ remove_column :users, :nickname
258
+ end
259
+ end
260
+ ```
261
+
262
+ **Good**
263
+
264
+ ```ruby
265
+ class AddNickname < ActiveRecord::Migration[8.0]
266
+ def change
267
+ add_column :users, :nickname, :string
268
+ end
269
+ end
270
+ ```
271
+
272
+ The cop is disabled by default. Enable it for migrations newer than a chosen version:
273
+
274
+ ```yaml
275
+ AllCops:
276
+ MigratedSchemaVersion: '20261030120000'
277
+
278
+ Betterment/NoDownMigrations:
279
+ Enabled: true
280
+ ```
281
+
282
+ Set `MigratedSchemaVersion` under this cop to ignore additional migrations.
283
+ Leave `Rails/ReversibleMigrationMethodDefinition` disabled: it requires `up` and `down`.
284
+
238
285
  ### Betterment/NonStandardActions
239
286
 
240
287
  This cop looks at Rails route files and flags routes that go to non-standard controller actions.
@@ -423,3 +470,24 @@ end
423
470
  ```
424
471
 
425
472
  This cop is disabled by default, because it reports many offenses in applications with older specs. To use it, enable it in your `.rubocop.yml`. By default it examines all files in `spec/`, except for the `features`, `requests`, `routing`, `system`, and `views` directories, where integration style tests that don't test one class and method are common. Examples in shared example groups are also ignored.
473
+
474
+ ### Betterment/NoSend
475
+
476
+ This cop flags calls to `send`, `public_send`, and `__send__`. Dynamic dispatch hides the call from Sorbet and code search, and `send` also reaches private methods. Call the method directly instead.
477
+
478
+ #### BAD:
479
+
480
+ ```ruby
481
+ record.public_send(:name)
482
+ record.send(attribute_name)
483
+ job.send(:plaid_item)
484
+ ```
485
+
486
+ #### GOOD:
487
+
488
+ ```ruby
489
+ record.name
490
+ record.attributes.fetch(attribute_name)
491
+ ```
492
+
493
+ This cop ignores files in `spec/`, and calls to `send` with no arguments, which are usually a different method named `send`.
data/config/default.yml CHANGED
@@ -20,7 +20,7 @@ AllCops:
20
20
  - Gemfile
21
21
  - bin/**/*
22
22
  - build/**/*
23
- - db/**/*
23
+ - db/*schema.rb
24
24
  - frontend/**/*
25
25
  - node_modules/**/*
26
26
  - tmp/**/*
@@ -62,6 +62,21 @@ Betterment/InternalsProtection:
62
62
  StyleGuide: '#bettermentinternalsprotection'
63
63
  Enabled: false
64
64
 
65
+ Betterment/NoDownMigrations:
66
+ Description: Disallows explicit rollback code in database migrations.
67
+ Enabled: false
68
+ MigratedSchemaVersion:
69
+ StyleGuide: '#bettermentnodownmigrations'
70
+ Include:
71
+ - db/migrate/**/*.rb
72
+
73
+ Betterment/NoSend:
74
+ Description: Detects dynamic method calls through send, public_send and __send__.
75
+ StyleGuide: '#bettermentnosend'
76
+ Enabled: true
77
+ Exclude:
78
+ - spec/**/*
79
+
65
80
  Betterment/NonNamespacedClass:
66
81
  Description: Detects classes that are not namespaced under a module or constant
67
82
  StyleGuide: '#bettermentnonamespacedclass'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Betterlint
4
- VERSION = '1.29.0'
4
+ VERSION = '1.31.0'
5
5
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop/cop/mixin/migrations_helper'
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module Betterment
8
+ class NoDownMigrations < Base
9
+ include MigrationsHelper
10
+
11
+ MSG = 'Do not write explicit rollback code. Correct deployed migrations with a new forward migration.'
12
+ RESTRICT_ON_SEND = %i(down).freeze
13
+
14
+ def on_def(node)
15
+ add_offense(node.loc.name) if node.method?(:down) && migration_to_check?(node)
16
+ end
17
+ alias on_defs on_def
18
+
19
+ def on_send(node)
20
+ if migration_to_check?(node) && reversible_direction?(node.receiver)
21
+ add_offense(node.loc.selector)
22
+ end
23
+ end
24
+ alias on_csend on_send
25
+
26
+ private
27
+
28
+ def migration_to_check?(node)
29
+ return false unless migration_class?(node.each_ancestor(:class).first)
30
+
31
+ cutoff = cop_config.fetch('MigratedSchemaVersion')
32
+ version = File.basename(processed_source.file_path)[/\A\d+(?=_)/]
33
+ !cutoff || !version || version.to_i > Integer(cutoff)
34
+ end
35
+
36
+ def reversible_direction?(receiver)
37
+ return false unless receiver&.lvar_type?
38
+
39
+ binding = receiver.each_ancestor(:any_block).find do |block|
40
+ block.argument_list.any? { |argument| argument.name == receiver.children.first }
41
+ end
42
+
43
+ binding&.method?(:reversible) && (binding.receiver.nil? || binding.receiver.self_type?)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Betterment
6
+ class NoSend < Base
7
+ MSG = <<~TEXT
8
+ Call the method directly instead of using `%<method>s`; dynamic dispatch is invisible to Sorbet and code search.
9
+
10
+ See here for more information on this cop:
11
+ https://github.com/Betterment/betterlint/blob/main/README.md#bettermentnosend
12
+ TEXT
13
+
14
+ RESTRICT_ON_SEND = %i(send public_send __send__).freeze
15
+
16
+ def on_send(node)
17
+ return unless node.arguments?
18
+
19
+ add_offense(node.loc.selector, message: format(MSG, method: node.method_name))
20
+ end
21
+ alias on_csend on_send
22
+ end
23
+ end
24
+ end
25
+ end
@@ -12,6 +12,8 @@ require 'rubocop/cop/betterment/hardcoded_id'
12
12
  require 'rubocop/cop/betterment/implicit_redirect_type'
13
13
  require 'rubocop/cop/betterment/internals_protection'
14
14
  require 'rubocop/cop/betterment/memoization_with_arguments'
15
+ require 'rubocop/cop/betterment/no_down_migrations'
16
+ require 'rubocop/cop/betterment/no_send'
15
17
  require 'rubocop/cop/betterment/non_namespaced_class'
16
18
  require 'rubocop/cop/betterment/non_standard_actions'
17
19
  require 'rubocop/cop/betterment/non_standard_controller'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: betterlint
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.29.0
4
+ version: 1.31.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Development
@@ -105,14 +105,14 @@ dependencies:
105
105
  requirements:
106
106
  - - "~>"
107
107
  - !ruby/object:Gem::Version
108
- version: '2.34'
108
+ version: '2.36'
109
109
  type: :runtime
110
110
  prerelease: false
111
111
  version_requirements: !ruby/object:Gem::Requirement
112
112
  requirements:
113
113
  - - "~>"
114
114
  - !ruby/object:Gem::Version
115
- version: '2.34'
115
+ version: '2.36'
116
116
  - !ruby/object:Gem::Dependency
117
117
  name: rubocop-rake
118
118
  requirement: !ruby/object:Gem::Requirement
@@ -179,6 +179,8 @@ files:
179
179
  - lib/rubocop/cop/betterment/implicit_redirect_type.rb
180
180
  - lib/rubocop/cop/betterment/internals_protection.rb
181
181
  - lib/rubocop/cop/betterment/memoization_with_arguments.rb
182
+ - lib/rubocop/cop/betterment/no_down_migrations.rb
183
+ - lib/rubocop/cop/betterment/no_send.rb
182
184
  - lib/rubocop/cop/betterment/non_namespaced_class.rb
183
185
  - lib/rubocop/cop/betterment/non_standard_actions.rb
184
186
  - lib/rubocop/cop/betterment/non_standard_controller.rb
@@ -203,10 +205,10 @@ licenses:
203
205
  - MIT
204
206
  metadata:
205
207
  homepage_uri: https://github.com/Betterment/betterlint
206
- source_code_uri: https://github.com/Betterment/betterlint/tree/v1.29.0
207
- changelog_uri: https://github.com/Betterment/betterlint/blob/v1.29.0/CHANGELOG.md
208
+ source_code_uri: https://github.com/Betterment/betterlint/tree/v1.31.0
209
+ changelog_uri: https://github.com/Betterment/betterlint/blob/v1.31.0/CHANGELOG.md
208
210
  bug_tracker_uri: https://github.com/Betterment/betterlint/issues
209
- documentation_uri: https://www.rubydoc.info/gems/betterlint/1.29.0
211
+ documentation_uri: https://www.rubydoc.info/gems/betterlint/1.31.0
210
212
  rubygems_mfa_required: 'true'
211
213
  default_lint_roller_plugin: Betterlint::Plugin
212
214
  rdoc_options: []
@@ -223,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
223
225
  - !ruby/object:Gem::Version
224
226
  version: '0'
225
227
  requirements: []
226
- rubygems_version: 4.0.13
228
+ rubygems_version: 4.0.24
227
229
  specification_version: 4
228
230
  summary: Betterment rubocop configuration
229
231
  test_files: []