betterlint 1.23.0 → 1.25.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/README.md +40 -2
- data/STYLEGUIDE.md +33 -0
- data/config/default.yml +4 -0
- data/lib/rubocop/cop/betterment/authorization_in_controller.rb +24 -11
- data/lib/rubocop/cop/betterment/simple_delegator.rb +26 -0
- data/lib/rubocop/cop/betterment/unscoped_find.rb +13 -4
- data/lib/rubocop/cop/betterment/utils/parser.rb +20 -3
- data/lib/rubocop/cop/betterment.rb +1 -1
- metadata +7 -7
- data/lib/rubocop/cop/betterment/utils/method_return_table.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04c560ef56ed92b4393449c238d64d433b16caa1db01dbcb81c647c04f9931d6
|
4
|
+
data.tar.gz: bac5e05a6ec457e6c047eba8c1d709549167ceae3b408fa084c5aa83c9594676
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57bf6d2446f5ec19e463e3bad15bb22934b08104a7614f08b1f67291bd8243ef7c1fdbccd7d8259f8b7b69c10f995248561c2e2cecf032c2bac01df2fd074aba
|
7
|
+
data.tar.gz: f2cee92d7b16ba483562f7bb1ebf822ff186e106cbf1df9f3f026f013f801a2f4f9fb01737e50b3e8bbfe83f4ee26af1b44614e35a48cf65028e7d3f6afb1dd2
|
data/README.md
CHANGED
@@ -142,13 +142,18 @@ If there isn't a better place to assign your environment variable, Rails provide
|
|
142
142
|
for [custom configuration](https://guides.rubyonrails.org/configuring.html#custom-configuration):
|
143
143
|
|
144
144
|
```ruby
|
145
|
-
config.x.whatever = ENV.fetch('WHATEVER')
|
145
|
+
config.x.some_namespace.whatever = ENV.fetch('WHATEVER')
|
146
146
|
```
|
147
147
|
|
148
148
|
Here's how you'd reference this configuration parameter at runtime:
|
149
149
|
|
150
150
|
```ruby
|
151
|
-
Rails.configuration.x.whatever
|
151
|
+
Rails.configuration.x.some_namespace.whatever
|
152
|
+
```
|
153
|
+
|
154
|
+
Or to raise an error when the value is not present
|
155
|
+
```ruby
|
156
|
+
Rails.configuration.x.some_namespace.whatever! # will raise "KeyError: :whatever is blank" when value is not set or set to nil
|
152
157
|
```
|
153
158
|
|
154
159
|
### Betterment/InternalsProtection
|
@@ -302,6 +307,39 @@ This cop requires you to explicitly provide an HTTP status code when rendering a
|
|
302
307
|
create, update, and destroy actions. When autocorrecting, this will automatically add
|
303
308
|
`status: :unprocessable_entity` or `status: :ok` depending on what you're rendering.
|
304
309
|
|
310
|
+
### Betterment/SimpleDelegator
|
311
|
+
|
312
|
+
This cop requires you to use Rails's `delegate` class method instead of `SimpleDelegator` in order to explicitly specify
|
313
|
+
the set of delegated methods.
|
314
|
+
|
315
|
+
#### BAD:
|
316
|
+
|
317
|
+
```ruby
|
318
|
+
class GearPresenter < SimpleDelegator
|
319
|
+
def ratio_string
|
320
|
+
ratio.to_s
|
321
|
+
end
|
322
|
+
end
|
323
|
+
```
|
324
|
+
|
325
|
+
#### GOOD:
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
class GearPresenter
|
329
|
+
attr_reader :gear
|
330
|
+
|
331
|
+
delegate :ratio, to: :gear
|
332
|
+
|
333
|
+
def initialize(gear)
|
334
|
+
@gear = gear
|
335
|
+
end
|
336
|
+
|
337
|
+
def ratio_string
|
338
|
+
ratio.to_s
|
339
|
+
end
|
340
|
+
end
|
341
|
+
```
|
342
|
+
|
305
343
|
### Betterment/UseGlobalStrictLoading/ByDefaultForModels
|
306
344
|
|
307
345
|
This cop identifies models where `self.strict_loading_by_default` is assigned to explicitly, and prefers that it be removed in favor of using the global strict loading settings.
|
data/STYLEGUIDE.md
CHANGED
@@ -109,3 +109,36 @@ expect(response).to have_http_status 422
|
|
109
109
|
expect(response).to have_http_status :internal_server_error
|
110
110
|
expect(response).to have_http_status 500
|
111
111
|
```
|
112
|
+
|
113
|
+
## Betterment/SimpleDelegator
|
114
|
+
|
115
|
+
This cop requires you to use Rail's `delegate` class method instead of `SimpleDelegator` in order to explicitly specify
|
116
|
+
the set of delegating methods.
|
117
|
+
|
118
|
+
### BAD:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
class GearPresenter < SimpleDelegator
|
122
|
+
def ratio_string
|
123
|
+
ratio.to_s
|
124
|
+
end
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
### GOOD:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
class GearDelegator
|
132
|
+
attr_reader :gear
|
133
|
+
|
134
|
+
delegate :ratio, to: :gear
|
135
|
+
|
136
|
+
def initialize(gear)
|
137
|
+
@gear = gear
|
138
|
+
end
|
139
|
+
|
140
|
+
def ratio_string
|
141
|
+
ratio.to_s
|
142
|
+
end
|
143
|
+
end
|
144
|
+
```
|
data/config/default.yml
CHANGED
@@ -95,6 +95,10 @@ Betterment/ServerErrorAssertion:
|
|
95
95
|
Include:
|
96
96
|
- spec/requests/**/*_spec.rb
|
97
97
|
|
98
|
+
Betterment/SimpleDelegator:
|
99
|
+
StyleGuide: '#bettermentsimpledelegator'
|
100
|
+
AutoCorrect: false
|
101
|
+
|
98
102
|
Betterment/SitePrismLoaded:
|
99
103
|
Include:
|
100
104
|
- spec/features/**/*_spec.rb
|
@@ -37,17 +37,17 @@ module RuboCop
|
|
37
37
|
super
|
38
38
|
@unsafe_parameters = cop_config.fetch("unsafe_parameters").map(&:to_sym)
|
39
39
|
@unsafe_regex = Regexp.new cop_config.fetch("unsafe_regex")
|
40
|
-
|
40
|
+
end
|
41
|
+
|
42
|
+
def on_new_investigation
|
43
|
+
super
|
44
|
+
@class_methods = {}.freeze
|
45
|
+
@param_wrappers = [].freeze
|
41
46
|
end
|
42
47
|
|
43
48
|
def on_class(node)
|
44
|
-
Utils::
|
45
|
-
|
46
|
-
method_returns.each do |x|
|
47
|
-
name = Utils::Parser.get_root_token(x)
|
48
|
-
@param_wrappers << method_name if name == :params || @param_wrappers.include?(name)
|
49
|
-
end
|
50
|
-
end
|
49
|
+
@class_methods = Utils::Parser.get_instance_methods(node).freeze
|
50
|
+
@param_wrappers = find_param_wrappers(@class_methods).freeze
|
51
51
|
end
|
52
52
|
|
53
53
|
def on_send(node) # rubocop:disable Metrics/PerceivedComplexity
|
@@ -88,7 +88,7 @@ module RuboCop
|
|
88
88
|
|
89
89
|
# Flags objects being created/updated with unsafe
|
90
90
|
# params indirectly from params or through params.permit
|
91
|
-
def flag_indirect_param_use(node) # rubocop:disable Metrics/PerceivedComplexity
|
91
|
+
def flag_indirect_param_use(node) # rubocop:disable Metrics/PerceivedComplexity
|
92
92
|
name = Utils::Parser.get_root_token(node)
|
93
93
|
# extracted_params contains parameters used like:
|
94
94
|
# def create
|
@@ -99,7 +99,7 @@ module RuboCop
|
|
99
99
|
# end
|
100
100
|
extracted_params = Utils::Parser.get_extracted_parameters(node, param_aliases: @param_wrappers)
|
101
101
|
|
102
|
-
returns =
|
102
|
+
returns = get_method_returns(name)
|
103
103
|
returns.each do |ret|
|
104
104
|
# # propagated_params contains parameters used like:
|
105
105
|
# def create
|
@@ -120,7 +120,7 @@ module RuboCop
|
|
120
120
|
if ret.send_type? && ret.method?(:[])
|
121
121
|
internal_params = ret.arguments.select { |x| x.sym_type? || x.str_type? }.map(&:value)
|
122
122
|
else
|
123
|
-
internal_returns =
|
123
|
+
internal_returns = get_method_returns(Utils::Parser.get_root_token(ret))
|
124
124
|
internal_params = internal_returns.flat_map { |x| Utils::Parser.get_extracted_parameters(x, param_aliases: @param_wrappers) }
|
125
125
|
end
|
126
126
|
|
@@ -144,6 +144,19 @@ module RuboCop
|
|
144
144
|
def suspicious_id?(symbol_name)
|
145
145
|
@unsafe_parameters.include?(symbol_name.to_sym) || @unsafe_regex.match(symbol_name) # symbol_name.to_s.end_with?("_id")
|
146
146
|
end
|
147
|
+
|
148
|
+
def find_param_wrappers(class_methods)
|
149
|
+
class_methods.each_with_object([]) do |(method_name, method_returns), param_wrappers|
|
150
|
+
param_wrappers << method_name if method_returns.any? do |return_value|
|
151
|
+
name = Utils::Parser.get_root_token(return_value)
|
152
|
+
name.equal?(:params) || param_wrappers.include?(name)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_method_returns(method_name)
|
158
|
+
@class_methods.fetch(method_name, [])
|
159
|
+
end
|
147
160
|
end
|
148
161
|
end
|
149
162
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Betterment
|
6
|
+
class SimpleDelegator < Base
|
7
|
+
MSG = <<~MSG
|
8
|
+
In order to specify a set of explicitly available methods,
|
9
|
+
use the `delegate` class method instead of `SimpleDelegator`.
|
10
|
+
|
11
|
+
See here for more information on this error:
|
12
|
+
https://github.com/Betterment/betterlint/#bettermentsimpledelegator
|
13
|
+
MSG
|
14
|
+
|
15
|
+
# @!method class_with_simple_delegator?(node)
|
16
|
+
def_node_matcher :class_with_simple_delegator?, <<~PATTERN
|
17
|
+
(class _ (const nil? :SimpleDelegator) _)
|
18
|
+
PATTERN
|
19
|
+
|
20
|
+
def on_class(node)
|
21
|
+
add_offense(node) if class_with_simple_delegator?(node)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -40,8 +40,13 @@ module RuboCop
|
|
40
40
|
@unauthenticated_models = cop_config.fetch("unauthenticated_models").map(&:to_sym)
|
41
41
|
end
|
42
42
|
|
43
|
+
def on_new_investigation
|
44
|
+
super
|
45
|
+
@class_methods = {}.freeze
|
46
|
+
end
|
47
|
+
|
43
48
|
def on_class(node)
|
44
|
-
Utils::
|
49
|
+
@class_methods = Utils::Parser.get_instance_methods(node).freeze
|
45
50
|
end
|
46
51
|
|
47
52
|
def on_send(node)
|
@@ -86,9 +91,7 @@ module RuboCop
|
|
86
91
|
|
87
92
|
def uses_params?(node)
|
88
93
|
root = Utils::Parser.get_root_token(node)
|
89
|
-
root
|
90
|
-
Utils::Parser.get_root_token(x) == :params
|
91
|
-
end
|
94
|
+
root.equal?(:params) || method_returns_params?(root)
|
92
95
|
end
|
93
96
|
|
94
97
|
# yoinked from Rails/DynamicFindBy
|
@@ -98,6 +101,12 @@ module RuboCop
|
|
98
101
|
|
99
102
|
match[2] ? 'find_by!' : 'find_by'
|
100
103
|
end
|
104
|
+
|
105
|
+
def method_returns_params?(method_name)
|
106
|
+
@class_methods.fetch(method_name, []).any? do |return_value|
|
107
|
+
Utils::Parser.get_root_token(return_value).equal?(:params)
|
108
|
+
end
|
109
|
+
end
|
101
110
|
end
|
102
111
|
end
|
103
112
|
end
|
@@ -88,16 +88,16 @@ module RuboCop
|
|
88
88
|
return [] unless node.send_type?
|
89
89
|
|
90
90
|
parameter_names = []
|
91
|
-
param_aliases
|
91
|
+
aliases = param_aliases | %i(params)
|
92
92
|
|
93
|
-
if node.method?(:[]) &&
|
93
|
+
if node.method?(:[]) && aliases.include?(get_root_token(node))
|
94
94
|
return node.arguments.select { |x|
|
95
95
|
x.sym_type? || x.str_type?
|
96
96
|
}.map(&:value)
|
97
97
|
end
|
98
98
|
|
99
99
|
children = node.descendants.select do |child|
|
100
|
-
child.send_type? &&
|
100
|
+
child.send_type? && aliases.include?(child.method_name)
|
101
101
|
end
|
102
102
|
|
103
103
|
children.each do |child|
|
@@ -112,6 +112,23 @@ module RuboCop
|
|
112
112
|
|
113
113
|
parameter_names.map(&:to_sym)
|
114
114
|
end
|
115
|
+
|
116
|
+
def self.get_instance_methods(node) # rubocop:disable Metrics/PerceivedComplexity
|
117
|
+
raise ArgumentError, 'must be a class node' unless node&.class_type?
|
118
|
+
|
119
|
+
methods = node.descendants.select(&:def_type?).to_h do |method|
|
120
|
+
[method.method_name, get_return_values(method)]
|
121
|
+
end
|
122
|
+
|
123
|
+
node.descendants.each do |descendant|
|
124
|
+
lhs, rhs = *descendant
|
125
|
+
if descendant.equals_asgn? && !descendant.type.equal?(:casgn) && rhs&.send_type?
|
126
|
+
methods[lhs] = [rhs]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
methods
|
131
|
+
end
|
115
132
|
end
|
116
133
|
end
|
117
134
|
end
|
@@ -18,6 +18,7 @@ require 'rubocop/cop/betterment/not_using_rswag'
|
|
18
18
|
require 'rubocop/cop/betterment/redirect_status'
|
19
19
|
require 'rubocop/cop/betterment/render_status'
|
20
20
|
require 'rubocop/cop/betterment/server_error_assertion'
|
21
|
+
require 'rubocop/cop/betterment/simple_delegator'
|
21
22
|
require 'rubocop/cop/betterment/site_prism_loaded'
|
22
23
|
require 'rubocop/cop/betterment/spec_helper_required_outside_spec_dir'
|
23
24
|
require 'rubocop/cop/betterment/timeout'
|
@@ -25,6 +26,5 @@ require 'rubocop/cop/betterment/unsafe_job'
|
|
25
26
|
require 'rubocop/cop/betterment/unscoped_find'
|
26
27
|
require 'rubocop/cop/betterment/use_global_strict_loading'
|
27
28
|
require 'rubocop/cop/betterment/utils/hardcoded_attribute'
|
28
|
-
require 'rubocop/cop/betterment/utils/method_return_table'
|
29
29
|
require 'rubocop/cop/betterment/utils/parser'
|
30
30
|
require 'rubocop/cop/betterment/vague_serialize'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: betterlint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Development
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: rubocop
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- lib/rubocop/cop/betterment/redirect_status.rb
|
122
122
|
- lib/rubocop/cop/betterment/render_status.rb
|
123
123
|
- lib/rubocop/cop/betterment/server_error_assertion.rb
|
124
|
+
- lib/rubocop/cop/betterment/simple_delegator.rb
|
124
125
|
- lib/rubocop/cop/betterment/site_prism_loaded.rb
|
125
126
|
- lib/rubocop/cop/betterment/spec_helper_required_outside_spec_dir.rb
|
126
127
|
- lib/rubocop/cop/betterment/timeout.rb
|
@@ -128,7 +129,6 @@ files:
|
|
128
129
|
- lib/rubocop/cop/betterment/unscoped_find.rb
|
129
130
|
- lib/rubocop/cop/betterment/use_global_strict_loading.rb
|
130
131
|
- lib/rubocop/cop/betterment/utils/hardcoded_attribute.rb
|
131
|
-
- lib/rubocop/cop/betterment/utils/method_return_table.rb
|
132
132
|
- lib/rubocop/cop/betterment/utils/parser.rb
|
133
133
|
- lib/rubocop/cop/betterment/utils/response_status.rb
|
134
134
|
- lib/rubocop/cop/betterment/vague_serialize.rb
|
@@ -137,10 +137,10 @@ licenses:
|
|
137
137
|
- MIT
|
138
138
|
metadata:
|
139
139
|
homepage_uri: https://github.com/Betterment/betterlint
|
140
|
-
source_code_uri: https://github.com/Betterment/betterlint/tree/v1.
|
141
|
-
changelog_uri: https://github.com/Betterment/betterlint/blob/v1.
|
140
|
+
source_code_uri: https://github.com/Betterment/betterlint/tree/v1.25.0
|
141
|
+
changelog_uri: https://github.com/Betterment/betterlint/blob/v1.25.0/CHANGELOG.md
|
142
142
|
bug_tracker_uri: https://github.com/Betterment/betterlint/issues
|
143
|
-
documentation_uri: https://www.rubydoc.info/gems/betterlint/1.
|
143
|
+
documentation_uri: https://www.rubydoc.info/gems/betterlint/1.25.0
|
144
144
|
rubygems_mfa_required: 'true'
|
145
145
|
rdoc_options: []
|
146
146
|
require_paths:
|
@@ -156,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
156
|
- !ruby/object:Gem::Version
|
157
157
|
version: '0'
|
158
158
|
requirements: []
|
159
|
-
rubygems_version: 3.6.
|
159
|
+
rubygems_version: 3.6.8
|
160
160
|
specification_version: 4
|
161
161
|
summary: Betterment rubocop configuration
|
162
162
|
test_files: []
|
@@ -1,52 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
module Cop
|
5
|
-
module Betterment
|
6
|
-
module Utils
|
7
|
-
module MethodReturnTable
|
8
|
-
class << self
|
9
|
-
def populate_index(node)
|
10
|
-
raise "not a class" unless node.class_type?
|
11
|
-
|
12
|
-
get_methods_for_class(node).each do |method|
|
13
|
-
track_method(method.method_name, Utils::Parser.get_return_values(method))
|
14
|
-
end
|
15
|
-
|
16
|
-
node.descendants.each do |descendant|
|
17
|
-
lhs, rhs = *descendant
|
18
|
-
next unless descendant.equals_asgn? && (descendant.type != :casgn) && rhs&.send_type?
|
19
|
-
|
20
|
-
track_method(lhs, [rhs])
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def indexed_methods
|
25
|
-
@indexed_methods ||= {}
|
26
|
-
end
|
27
|
-
|
28
|
-
def get_method(method_name)
|
29
|
-
indexed_methods[method_name]
|
30
|
-
end
|
31
|
-
|
32
|
-
def has_method?(method_name)
|
33
|
-
indexed_methods.include?(method_name)
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def track_method(method_name, returns)
|
39
|
-
indexed_methods[method_name] = returns
|
40
|
-
end
|
41
|
-
|
42
|
-
def get_methods_for_class(node)
|
43
|
-
return [] unless node.children && node.class_type?
|
44
|
-
|
45
|
-
node.descendants.select(&:def_type?)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|