rubocop-rails 2.7.1 → 2.10.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/LICENSE.txt +1 -1
- data/README.md +18 -2
- data/config/default.yml +144 -6
- data/config/obsoletion.yml +7 -0
- data/lib/rubocop/cop/mixin/active_record_helper.rb +16 -3
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +40 -0
- data/lib/rubocop/cop/mixin/index_method.rb +25 -11
- data/lib/rubocop/cop/rails/action_filter.rb +10 -14
- data/lib/rubocop/cop/rails/active_record_aliases.rb +13 -17
- data/lib/rubocop/cop/rails/active_record_callbacks_order.rb +19 -16
- data/lib/rubocop/cop/rails/active_record_override.rb +1 -1
- data/lib/rubocop/cop/rails/active_support_aliases.rb +12 -21
- data/lib/rubocop/cop/rails/after_commit_override.rb +91 -0
- data/lib/rubocop/cop/rails/application_controller.rb +3 -7
- data/lib/rubocop/cop/rails/application_job.rb +2 -1
- data/lib/rubocop/cop/rails/application_mailer.rb +2 -7
- data/lib/rubocop/cop/rails/application_record.rb +2 -7
- data/lib/rubocop/cop/rails/arel_star.rb +41 -0
- data/lib/rubocop/cop/rails/assert_not.rb +8 -10
- data/lib/rubocop/cop/rails/attribute_default_block_value.rb +90 -0
- data/lib/rubocop/cop/rails/belongs_to.rb +10 -19
- data/lib/rubocop/cop/rails/blank.rb +31 -27
- data/lib/rubocop/cop/rails/bulk_change_table.rb +1 -1
- data/lib/rubocop/cop/rails/content_tag.rb +34 -19
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +2 -1
- data/lib/rubocop/cop/rails/date.rb +10 -11
- data/lib/rubocop/cop/rails/default_scope.rb +11 -4
- data/lib/rubocop/cop/rails/delegate.rb +9 -9
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +7 -8
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +15 -12
- data/lib/rubocop/cop/rails/enum_hash.rb +11 -10
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -1
- data/lib/rubocop/cop/rails/environment_comparison.rb +18 -14
- data/lib/rubocop/cop/rails/environment_variable_access.rb +67 -0
- data/lib/rubocop/cop/rails/exit.rb +4 -10
- data/lib/rubocop/cop/rails/file_path.rb +7 -8
- data/lib/rubocop/cop/rails/find_by.rb +13 -13
- data/lib/rubocop/cop/rails/find_by_id.rb +12 -21
- data/lib/rubocop/cop/rails/find_each.rb +19 -18
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
- data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +37 -10
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +30 -2
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +32 -21
- data/lib/rubocop/cop/rails/http_status.rb +7 -9
- data/lib/rubocop/cop/rails/ignored_skip_action_filter_option.rb +8 -6
- data/lib/rubocop/cop/rails/index_by.rb +11 -2
- data/lib/rubocop/cop/rails/index_with.rb +11 -2
- data/lib/rubocop/cop/rails/inquiry.rb +7 -2
- data/lib/rubocop/cop/rails/inverse_of.rb +3 -2
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +17 -15
- data/lib/rubocop/cop/rails/link_to_blank.rb +25 -23
- data/lib/rubocop/cop/rails/mailer_name.rb +19 -13
- data/lib/rubocop/cop/rails/match_route.rb +14 -13
- data/lib/rubocop/cop/rails/negate_include.rb +10 -8
- data/lib/rubocop/cop/rails/not_null_column.rb +2 -1
- data/lib/rubocop/cop/rails/order_by_id.rb +52 -0
- data/lib/rubocop/cop/rails/output.rb +5 -2
- data/lib/rubocop/cop/rails/output_safety.rb +3 -2
- data/lib/rubocop/cop/rails/pick.rb +14 -12
- data/lib/rubocop/cop/rails/pluck.rb +6 -9
- data/lib/rubocop/cop/rails/pluck_id.rb +4 -6
- data/lib/rubocop/cop/rails/pluck_in_where.rb +39 -5
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +10 -14
- data/lib/rubocop/cop/rails/presence.rb +12 -13
- data/lib/rubocop/cop/rails/present.rb +30 -24
- data/lib/rubocop/cop/rails/rake_environment.rb +8 -10
- data/lib/rubocop/cop/rails/read_write_attribute.rb +12 -11
- data/lib/rubocop/cop/rails/redundant_allow_nil.rb +29 -31
- data/lib/rubocop/cop/rails/redundant_foreign_key.rb +9 -12
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +11 -10
- data/lib/rubocop/cop/rails/reflection_class_name.rb +18 -4
- data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
- data/lib/rubocop/cop/rails/relative_date_constant.rb +34 -22
- data/lib/rubocop/cop/rails/render_inline.rb +2 -1
- data/lib/rubocop/cop/rails/render_plain_text.rb +9 -14
- data/lib/rubocop/cop/rails/request_referer.rb +7 -7
- data/lib/rubocop/cop/rails/require_dependency.rb +38 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +83 -8
- data/lib/rubocop/cop/rails/reversible_migration_method_definition.rb +75 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +30 -11
- data/lib/rubocop/cop/rails/safe_navigation_with_blank.rb +5 -10
- data/lib/rubocop/cop/rails/save_bang.rb +19 -22
- data/lib/rubocop/cop/rails/scope_args.rb +2 -1
- data/lib/rubocop/cop/rails/short_i18n.rb +7 -9
- data/lib/rubocop/cop/rails/skips_model_validations.rb +4 -4
- data/lib/rubocop/cop/rails/squished_sql_heredocs.rb +82 -0
- data/lib/rubocop/cop/rails/time_zone.rb +35 -25
- data/lib/rubocop/cop/rails/time_zone_assignment.rb +37 -0
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +6 -6
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +18 -8
- data/lib/rubocop/cop/rails/unknown_env.rb +3 -3
- data/lib/rubocop/cop/rails/validation.rb +15 -14
- data/lib/rubocop/cop/rails/where_equals.rb +98 -0
- data/lib/rubocop/cop/rails/where_exists.rb +85 -16
- data/lib/rubocop/cop/rails/where_not.rb +101 -0
- data/lib/rubocop/cop/rails_cops.rb +12 -0
- data/lib/rubocop/rails.rb +2 -0
- data/lib/rubocop/rails/schema_loader.rb +4 -4
- data/lib/rubocop/rails/schema_loader/schema.rb +4 -8
- data/lib/rubocop/rails/version.rb +5 -1
- metadata +33 -14
@@ -40,8 +40,9 @@ module RuboCop
|
|
40
40
|
#
|
41
41
|
# t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP' }
|
42
42
|
# end
|
43
|
-
class CreateTableWithTimestamps <
|
43
|
+
class CreateTableWithTimestamps < Base
|
44
44
|
MSG = 'Add timestamps when creating a new table.'
|
45
|
+
RESTRICT_ON_SEND = %i[create_table].freeze
|
45
46
|
|
46
47
|
def_node_matcher :create_table_with_block?, <<~PATTERN
|
47
48
|
(block
|
@@ -43,7 +43,7 @@ module RuboCop
|
|
43
43
|
# Date.yesterday
|
44
44
|
# date.in_time_zone
|
45
45
|
#
|
46
|
-
class Date <
|
46
|
+
class Date < Base
|
47
47
|
include ConfigurableEnforcedStyle
|
48
48
|
|
49
49
|
MSG = 'Do not use `Date.%<method_called>s` without zone. Use ' \
|
@@ -52,6 +52,8 @@ module RuboCop
|
|
52
52
|
MSG_SEND = 'Do not use `%<method>s` on Date objects, because they ' \
|
53
53
|
'know nothing about the time zone in use.'
|
54
54
|
|
55
|
+
RESTRICT_ON_SEND = %i[to_time to_time_in_current_zone].freeze
|
56
|
+
|
55
57
|
BAD_DAYS = %i[today current yesterday tomorrow].freeze
|
56
58
|
|
57
59
|
DEPRECATED_METHODS = [
|
@@ -76,8 +78,7 @@ module RuboCop
|
|
76
78
|
|
77
79
|
check_deprecated_methods(node)
|
78
80
|
|
79
|
-
add_offense(node,
|
80
|
-
message: format(MSG_SEND, method: node.method_name))
|
81
|
+
add_offense(node.loc.selector, message: format(MSG_SEND, method: node.method_name))
|
81
82
|
end
|
82
83
|
alias on_csend on_send
|
83
84
|
|
@@ -87,10 +88,9 @@ module RuboCop
|
|
87
88
|
DEPRECATED_METHODS.each do |method|
|
88
89
|
next unless node.method?(method[:deprecated].to_sym)
|
89
90
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
relevant: method[:relevant]))
|
91
|
+
message = format(DEPRECATED_MSG, deprecated: method[:deprecated], relevant: method[:relevant])
|
92
|
+
|
93
|
+
add_offense(node.loc.selector, message: message)
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
@@ -104,10 +104,9 @@ module RuboCop
|
|
104
104
|
day = method_name
|
105
105
|
day = 'today' if method_name == 'current'
|
106
106
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
day: day))
|
107
|
+
message = format(MSG, method_called: method_name, day: day)
|
108
|
+
|
109
|
+
add_offense(node.loc.selector, message: message)
|
111
110
|
end
|
112
111
|
|
113
112
|
def extract_method_chain(node)
|
@@ -22,8 +22,9 @@ module RuboCop
|
|
22
22
|
# where(hidden: false)
|
23
23
|
# end
|
24
24
|
#
|
25
|
-
class DefaultScope <
|
25
|
+
class DefaultScope < Base
|
26
26
|
MSG = 'Avoid use of `default_scope`. It is better to use explicitly named scopes.'
|
27
|
+
RESTRICT_ON_SEND = %i[default_scope].freeze
|
27
28
|
|
28
29
|
def_node_matcher :method_call?, <<~PATTERN
|
29
30
|
(send nil? :default_scope ...)
|
@@ -38,15 +39,21 @@ module RuboCop
|
|
38
39
|
PATTERN
|
39
40
|
|
40
41
|
def on_send(node)
|
41
|
-
|
42
|
+
return unless method_call?(node)
|
43
|
+
|
44
|
+
add_offense(node.loc.selector)
|
42
45
|
end
|
43
46
|
|
44
47
|
def on_defs(node)
|
45
|
-
|
48
|
+
return unless class_method_definition?(node)
|
49
|
+
|
50
|
+
add_offense(node.loc.name)
|
46
51
|
end
|
47
52
|
|
48
53
|
def on_sclass(node)
|
49
|
-
eigenclass_method_definition?(node)
|
54
|
+
eigenclass_method_definition?(node) do |default_scope|
|
55
|
+
add_offense(default_scope.loc.name)
|
56
|
+
end
|
50
57
|
end
|
51
58
|
end
|
52
59
|
end
|
@@ -52,7 +52,9 @@ module RuboCop
|
|
52
52
|
#
|
53
53
|
# # good
|
54
54
|
# delegate :bar, to: :foo, prefix: true
|
55
|
-
class Delegate <
|
55
|
+
class Delegate < Base
|
56
|
+
extend AutoCorrector
|
57
|
+
|
56
58
|
MSG = 'Use `delegate` to define delegations.'
|
57
59
|
|
58
60
|
def_node_matcher :delegate?, <<~PATTERN
|
@@ -64,22 +66,20 @@ module RuboCop
|
|
64
66
|
return unless trivial_delegate?(node)
|
65
67
|
return if private_or_protected_delegation(node)
|
66
68
|
|
67
|
-
|
69
|
+
register_offense(node)
|
68
70
|
end
|
69
71
|
|
70
|
-
|
71
|
-
delegation = ["delegate :#{node.body.method_name}",
|
72
|
-
"to: :#{node.body.receiver.method_name}"]
|
72
|
+
private
|
73
73
|
|
74
|
-
|
74
|
+
def register_offense(node)
|
75
|
+
add_offense(node.loc.keyword) do |corrector|
|
76
|
+
delegation = ["delegate :#{node.body.method_name}", "to: :#{node.body.receiver.method_name}"]
|
77
|
+
delegation << ['prefix: true'] if node.method?(prefixed_method_name(node.body))
|
75
78
|
|
76
|
-
lambda do |corrector|
|
77
79
|
corrector.replace(node.source_range, delegation.join(', '))
|
78
80
|
end
|
79
81
|
end
|
80
82
|
|
81
|
-
private
|
82
|
-
|
83
83
|
def trivial_delegate?(def_node)
|
84
84
|
delegate?(def_node) &&
|
85
85
|
method_name_matches?(def_node.method_name, def_node.body) &&
|
@@ -13,22 +13,21 @@ module RuboCop
|
|
13
13
|
#
|
14
14
|
# # good
|
15
15
|
# delegate :foo, to: :bar, allow_nil: true
|
16
|
-
class DelegateAllowBlank <
|
16
|
+
class DelegateAllowBlank < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
17
19
|
MSG = '`allow_blank` is not a valid option, use `allow_nil`.'
|
20
|
+
RESTRICT_ON_SEND = %i[delegate].freeze
|
18
21
|
|
19
22
|
def_node_matcher :allow_blank_option, <<~PATTERN
|
20
23
|
(send nil? :delegate _ (hash <$(pair (sym :allow_blank) true) ...>))
|
21
24
|
PATTERN
|
22
25
|
|
23
26
|
def on_send(node)
|
24
|
-
allow_blank_option(node)
|
25
|
-
add_offense(offending_node)
|
26
|
-
end
|
27
|
-
end
|
27
|
+
return unless (offending_node = allow_blank_option(node))
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
corrector.replace(pair_node.key.source_range, 'allow_nil')
|
29
|
+
add_offense(offending_node) do |corrector|
|
30
|
+
corrector.replace(offending_node.key.source_range, 'allow_nil')
|
32
31
|
end
|
33
32
|
end
|
34
33
|
end
|
@@ -31,36 +31,39 @@ module RuboCop
|
|
31
31
|
#
|
32
32
|
# # good
|
33
33
|
# Gem::Specification.find_by_name('backend').gem_dir
|
34
|
-
class DynamicFindBy <
|
34
|
+
class DynamicFindBy < Base
|
35
|
+
include ActiveRecordHelper
|
36
|
+
extend AutoCorrector
|
37
|
+
|
35
38
|
MSG = 'Use `%<static_name>s` instead of dynamic `%<method>s`.'
|
36
39
|
METHOD_PATTERN = /^find_by_(.+?)(!)?$/.freeze
|
37
40
|
|
38
41
|
def on_send(node)
|
39
|
-
return if allowed_invocation?(node)
|
42
|
+
return if node.receiver.nil? && !inherit_active_record_base?(node) || allowed_invocation?(node)
|
40
43
|
|
41
44
|
method_name = node.method_name
|
42
45
|
static_name = static_method_name(method_name)
|
43
46
|
return unless static_name
|
47
|
+
return if node.arguments.any?(&:splat_type?)
|
44
48
|
|
45
|
-
|
46
|
-
|
47
|
-
|
49
|
+
message = format(MSG, static_name: static_name, method: method_name)
|
50
|
+
add_offense(node, message: message) do |corrector|
|
51
|
+
autocorrect(corrector, node)
|
52
|
+
end
|
48
53
|
end
|
49
54
|
alias on_csend on_send
|
50
55
|
|
51
|
-
|
56
|
+
private
|
57
|
+
|
58
|
+
def autocorrect(corrector, node)
|
52
59
|
keywords = column_keywords(node.method_name)
|
53
60
|
|
54
61
|
return if keywords.size != node.arguments.size
|
55
62
|
|
56
|
-
|
57
|
-
|
58
|
-
autocorrect_argument_keywords(corrector, node, keywords)
|
59
|
-
end
|
63
|
+
autocorrect_method_name(corrector, node)
|
64
|
+
autocorrect_argument_keywords(corrector, node, keywords)
|
60
65
|
end
|
61
66
|
|
62
|
-
private
|
63
|
-
|
64
67
|
def allowed_invocation?(node)
|
65
68
|
allowed_method?(node) || allowed_receiver?(node) ||
|
66
69
|
whitelisted?(node)
|
@@ -17,9 +17,12 @@ module RuboCop
|
|
17
17
|
# # good
|
18
18
|
# enum status: { active: 0, archived: 1 }
|
19
19
|
#
|
20
|
-
class EnumHash <
|
20
|
+
class EnumHash < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
21
23
|
MSG = 'Enum defined as an array found in `%<enum>s` enum declaration. '\
|
22
24
|
'Use hash syntax instead.'
|
25
|
+
RESTRICT_ON_SEND = %i[enum].freeze
|
23
26
|
|
24
27
|
def_node_matcher :enum?, <<~PATTERN
|
25
28
|
(send nil? :enum (hash $...))
|
@@ -35,19 +38,17 @@ module RuboCop
|
|
35
38
|
key, array = array_pair?(pair)
|
36
39
|
next unless key
|
37
40
|
|
38
|
-
add_offense(array, message: format(MSG, enum: enum_name(key)))
|
41
|
+
add_offense(array, message: format(MSG, enum: enum_name(key))) do |corrector|
|
42
|
+
hash = array.children.each_with_index.map do |elem, index|
|
43
|
+
"#{source(elem)} => #{index}"
|
44
|
+
end.join(', ')
|
45
|
+
|
46
|
+
corrector.replace(array.loc.expression, "{#{hash}}")
|
47
|
+
end
|
39
48
|
end
|
40
49
|
end
|
41
50
|
end
|
42
51
|
|
43
|
-
def autocorrect(node)
|
44
|
-
hash = node.children.each_with_index.map do |elem, index|
|
45
|
-
"#{source(elem)} => #{index}"
|
46
|
-
end.join(', ')
|
47
|
-
|
48
|
-
->(corrector) { corrector.replace(node.loc.expression, "{#{hash}}") }
|
49
|
-
end
|
50
|
-
|
51
52
|
private
|
52
53
|
|
53
54
|
def enum_name(key)
|
@@ -17,11 +17,12 @@ module RuboCop
|
|
17
17
|
#
|
18
18
|
# # good
|
19
19
|
# enum status: [:active, :archived]
|
20
|
-
class EnumUniqueness <
|
20
|
+
class EnumUniqueness < Base
|
21
21
|
include Duplication
|
22
22
|
|
23
23
|
MSG = 'Duplicate value `%<value>s` found in `%<enum>s` ' \
|
24
24
|
'enum declaration.'
|
25
|
+
RESTRICT_ON_SEND = %i[enum].freeze
|
25
26
|
|
26
27
|
def_node_matcher :enum?, <<~PATTERN
|
27
28
|
(send nil? :enum (hash $...))
|
@@ -15,12 +15,16 @@ module RuboCop
|
|
15
15
|
#
|
16
16
|
# # good
|
17
17
|
# Rails.env.production?
|
18
|
-
class EnvironmentComparison <
|
18
|
+
class EnvironmentComparison < Base
|
19
|
+
extend AutoCorrector
|
20
|
+
|
19
21
|
MSG = 'Favor `%<bang>sRails.env.%<env>s?` over `%<source>s`.'
|
20
22
|
|
21
23
|
SYM_MSG = 'Do not compare `Rails.env` with a symbol, it will always ' \
|
22
24
|
'evaluate to `false`.'
|
23
25
|
|
26
|
+
RESTRICT_ON_SEND = %i[== !=].freeze
|
27
|
+
|
24
28
|
def_node_matcher :comparing_str_env_with_rails_env_on_lhs?, <<~PATTERN
|
25
29
|
(send
|
26
30
|
(send (const {nil? cbase} :Rails) :env)
|
@@ -62,28 +66,28 @@ module RuboCop
|
|
62
66
|
comparing_str_env_with_rails_env_on_rhs?(node))
|
63
67
|
env, = *env_node
|
64
68
|
bang = node.method?(:!=) ? '!' : ''
|
69
|
+
message = format(MSG, bang: bang, env: env, source: node.source)
|
65
70
|
|
66
|
-
add_offense(node, message:
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
if comparing_sym_env_with_rails_env_on_lhs?(node) ||
|
72
|
-
comparing_sym_env_with_rails_env_on_rhs?(node)
|
73
|
-
add_offense(node, message: SYM_MSG)
|
71
|
+
add_offense(node, message: message) do |corrector|
|
72
|
+
autocorrect(corrector, node)
|
73
|
+
end
|
74
74
|
end
|
75
|
-
end
|
76
75
|
|
77
|
-
|
78
|
-
lambda do |corrector|
|
79
|
-
replacement = build_predicate_method(node)
|
76
|
+
return unless comparing_sym_env_with_rails_env_on_lhs?(node) || comparing_sym_env_with_rails_env_on_rhs?(node)
|
80
77
|
|
81
|
-
|
78
|
+
add_offense(node, message: SYM_MSG) do |corrector|
|
79
|
+
autocorrect(corrector, node)
|
82
80
|
end
|
83
81
|
end
|
84
82
|
|
85
83
|
private
|
86
84
|
|
85
|
+
def autocorrect(corrector, node)
|
86
|
+
replacement = build_predicate_method(node)
|
87
|
+
|
88
|
+
corrector.replace(node.source_range, replacement)
|
89
|
+
end
|
90
|
+
|
87
91
|
def build_predicate_method(node)
|
88
92
|
if rails_env_on_lhs?(node)
|
89
93
|
build_predicate_method_for_rails_env_on_lhs(node)
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop looks for direct access to environment variables through the
|
7
|
+
# `ENV` variable within the application code. This can lead to runtime
|
8
|
+
# errors due to misconfiguration that could have been discovered at boot
|
9
|
+
# time if the environment variables were loaded as part of initialization
|
10
|
+
# and copied into the application's configuration or secrets. The cop can
|
11
|
+
# be configured to allow either reads or writes if required.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # good
|
15
|
+
# Rails.application.config.foo
|
16
|
+
# Rails.application.config.x.foo.bar
|
17
|
+
# Rails.application.secrets.foo
|
18
|
+
# Rails.application.config.foo = "bar"
|
19
|
+
#
|
20
|
+
# @example AllowReads: false (default)
|
21
|
+
# # bad
|
22
|
+
# ENV["FOO"]
|
23
|
+
# ENV.fetch("FOO")
|
24
|
+
#
|
25
|
+
# @example AllowReads: true
|
26
|
+
# # good
|
27
|
+
# ENV["FOO"]
|
28
|
+
# ENV.fetch("FOO")
|
29
|
+
#
|
30
|
+
# @example AllowWrites: false (default)
|
31
|
+
# # bad
|
32
|
+
# ENV["FOO"] = "bar"
|
33
|
+
#
|
34
|
+
# @example AllowWrites: true
|
35
|
+
# # good
|
36
|
+
# ENV["FOO"] = "bar"
|
37
|
+
class EnvironmentVariableAccess < Base
|
38
|
+
READ_MSG = 'Do not read from `ENV` directly post initialization.'
|
39
|
+
WRITE_MSG = 'Do not write to `ENV` directly post initialization.'
|
40
|
+
|
41
|
+
def on_const(node)
|
42
|
+
add_offense(node, message: READ_MSG) if env_read?(node) && !allow_reads?
|
43
|
+
add_offense(node, message: WRITE_MSG) if env_write?(node) && !allow_writes?
|
44
|
+
end
|
45
|
+
|
46
|
+
def_node_search :env_read?, <<~PATTERN
|
47
|
+
^(send (const {cbase nil?} :ENV) !:[]= ...)
|
48
|
+
PATTERN
|
49
|
+
|
50
|
+
def_node_search :env_write?, <<~PATTERN
|
51
|
+
{^(indexasgn (const {cbase nil?} :ENV) ...)
|
52
|
+
^(send (const {cbase nil?} :ENV) :[]= ...)}
|
53
|
+
PATTERN
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def allow_reads?
|
58
|
+
cop_config['AllowReads'] == true
|
59
|
+
end
|
60
|
+
|
61
|
+
def allow_writes?
|
62
|
+
cop_config['AllowWrites'] == true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -23,27 +23,21 @@ module RuboCop
|
|
23
23
|
#
|
24
24
|
# # good
|
25
25
|
# raise 'a bad error has happened'
|
26
|
-
class Exit <
|
26
|
+
class Exit < Base
|
27
27
|
include ConfigurableEnforcedStyle
|
28
28
|
|
29
29
|
MSG = 'Do not use `exit` in Rails applications.'
|
30
|
-
|
30
|
+
RESTRICT_ON_SEND = %i[exit exit!].freeze
|
31
31
|
EXPLICIT_RECEIVERS = %i[Kernel Process].freeze
|
32
32
|
|
33
33
|
def on_send(node)
|
34
|
-
add_offense(node
|
34
|
+
add_offense(node.loc.selector) if offending_node?(node)
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
38
38
|
|
39
39
|
def offending_node?(node)
|
40
|
-
|
41
|
-
right_argument_count?(node.arguments) &&
|
42
|
-
right_receiver?(node.receiver)
|
43
|
-
end
|
44
|
-
|
45
|
-
def right_method_name?(method_name)
|
46
|
-
TARGET_METHODS.include?(method_name)
|
40
|
+
right_argument_count?(node.arguments) && right_receiver?(node.receiver)
|
47
41
|
end
|
48
42
|
|
49
43
|
# More than 1 argument likely means it is a different
|
@@ -25,14 +25,13 @@ module RuboCop
|
|
25
25
|
# # good
|
26
26
|
# Rails.root.join('app/models/goober')
|
27
27
|
#
|
28
|
-
class FilePath <
|
28
|
+
class FilePath < Base
|
29
29
|
include ConfigurableEnforcedStyle
|
30
30
|
include RangeHelp
|
31
31
|
|
32
|
-
MSG_SLASHES = '
|
33
|
-
|
34
|
-
|
35
|
-
'instead.'
|
32
|
+
MSG_SLASHES = 'Prefer `Rails.root.join(\'path/to\')`.'
|
33
|
+
MSG_ARGUMENTS = 'Prefer `Rails.root.join(\'path\', \'to\')`.'
|
34
|
+
RESTRICT_ON_SEND = %i[join].freeze
|
36
35
|
|
37
36
|
def_node_matcher :file_join_nodes?, <<~PATTERN
|
38
37
|
(send (const nil? :File) :join ...)
|
@@ -90,17 +89,17 @@ module RuboCop
|
|
90
89
|
end
|
91
90
|
|
92
91
|
def string_with_slash?(node)
|
93
|
-
node.str_type? && node.source.
|
92
|
+
node.str_type? && node.source.include?('/')
|
94
93
|
end
|
95
94
|
|
96
95
|
def register_offense(node)
|
97
96
|
line_range = node.loc.column...node.loc.last_column
|
98
97
|
source_range = source_range(processed_source.buffer, node.first_line,
|
99
98
|
line_range)
|
100
|
-
add_offense(
|
99
|
+
add_offense(source_range)
|
101
100
|
end
|
102
101
|
|
103
|
-
def message(
|
102
|
+
def message(_range)
|
104
103
|
format(style == :arguments ? MSG_ARGUMENTS : MSG_SLASHES)
|
105
104
|
end
|
106
105
|
end
|