rubocop-rails 2.8.0 → 2.10.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 +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +18 -2
- data/config/default.yml +101 -5
- 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 +8 -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 +17 -12
- 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 +9 -2
- 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 +33 -18
- 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 +6 -7
- 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 -6
- data/lib/rubocop/cop/rails/helper_instance_variable.rb +29 -3
- 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 +3 -2
- data/lib/rubocop/cop/rails/index_with.rb +3 -2
- data/lib/rubocop/cop/rails/inquiry.rb +4 -3
- 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 +1 -2
- 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 +7 -7
- 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 +17 -3
- data/lib/rubocop/cop/rails/refute_methods.rb +9 -10
- data/lib/rubocop/cop/rails/relative_date_constant.rb +30 -21
- 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 +4 -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 +17 -20
- 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 +5 -6
- 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 +4 -6
- data/lib/rubocop/cop/rails/unique_validation_without_index.rb +4 -2
- 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 +19 -13
- data/lib/rubocop/cop/rails/where_not.rb +14 -19
- data/lib/rubocop/cop/rails_cops.rb +8 -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 +2 -4
- data/lib/rubocop/rails/version.rb +5 -1
- metadata +29 -14
@@ -12,7 +12,9 @@ module RuboCop
|
|
12
12
|
#
|
13
13
|
# #good
|
14
14
|
# Book.update!(author: 'Alice')
|
15
|
-
class ActiveRecordAliases <
|
15
|
+
class ActiveRecordAliases < Base
|
16
|
+
extend AutoCorrector
|
17
|
+
|
16
18
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
17
19
|
|
18
20
|
ALIASES = {
|
@@ -20,28 +22,22 @@ module RuboCop
|
|
20
22
|
update_attributes!: :update!
|
21
23
|
}.freeze
|
22
24
|
|
25
|
+
RESTRICT_ON_SEND = ALIASES.keys.freeze
|
26
|
+
|
23
27
|
def on_send(node)
|
24
|
-
|
25
|
-
|
28
|
+
method_name = node.method_name
|
29
|
+
alias_method = ALIASES[method_name]
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
add_offense(
|
32
|
+
node.loc.selector,
|
33
|
+
message: format(MSG, prefer: alias_method, current: method_name),
|
34
|
+
severity: :warning
|
35
|
+
) do |corrector|
|
36
|
+
corrector.replace(node.loc.selector, alias_method)
|
32
37
|
end
|
33
38
|
end
|
34
39
|
|
35
40
|
alias on_csend on_send
|
36
|
-
|
37
|
-
def autocorrect(node)
|
38
|
-
lambda do |corrector|
|
39
|
-
corrector.replace(
|
40
|
-
node.loc.selector,
|
41
|
-
ALIASES[node.method_name].to_s
|
42
|
-
)
|
43
|
-
end
|
44
|
-
end
|
45
41
|
end
|
46
42
|
end
|
47
43
|
end
|
@@ -19,7 +19,9 @@ module RuboCop
|
|
19
19
|
# after_commit :after_commit_callback
|
20
20
|
# end
|
21
21
|
#
|
22
|
-
class ActiveRecordCallbacksOrder <
|
22
|
+
class ActiveRecordCallbacksOrder < Base
|
23
|
+
extend AutoCorrector
|
24
|
+
|
23
25
|
MSG = '`%<current>s` is supposed to appear before `%<previous>s`.'
|
24
26
|
|
25
27
|
CALLBACKS_IN_ORDER = %i[
|
@@ -55,17 +57,20 @@ module RuboCop
|
|
55
57
|
index = CALLBACKS_ORDER_MAP[callback]
|
56
58
|
|
57
59
|
if index < previous_index
|
58
|
-
message = format(MSG, current: callback,
|
59
|
-
|
60
|
-
|
60
|
+
message = format(MSG, current: callback, previous: previous_callback)
|
61
|
+
add_offense(node, message: message) do |corrector|
|
62
|
+
autocorrect(corrector, node)
|
63
|
+
end
|
61
64
|
end
|
62
65
|
previous_index = index
|
63
66
|
previous_callback = callback
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
70
|
+
private
|
71
|
+
|
67
72
|
# Autocorrect by swapping between two nodes autocorrecting them
|
68
|
-
def autocorrect(node)
|
73
|
+
def autocorrect(corrector, node)
|
69
74
|
previous = left_siblings_of(node).reverse_each.find do |sibling|
|
70
75
|
callback?(sibling)
|
71
76
|
end
|
@@ -73,14 +78,10 @@ module RuboCop
|
|
73
78
|
current_range = source_range_with_comment(node)
|
74
79
|
previous_range = source_range_with_comment(previous)
|
75
80
|
|
76
|
-
|
77
|
-
|
78
|
-
corrector.remove(current_range)
|
79
|
-
end
|
81
|
+
corrector.insert_before(previous_range, current_range.source)
|
82
|
+
corrector.remove(current_range)
|
80
83
|
end
|
81
84
|
|
82
|
-
private
|
83
|
-
|
84
85
|
def defined_callbacks(class_node)
|
85
86
|
class_def = class_node.body
|
86
87
|
|
@@ -121,7 +122,7 @@ module RuboCop
|
|
121
122
|
|
122
123
|
processed_source.comments_before_line(annotation_line)
|
123
124
|
.reverse_each do |comment|
|
124
|
-
if comment.location.line == annotation_line
|
125
|
+
if comment.location.line == annotation_line && !inline_comment?(comment)
|
125
126
|
first_comment = comment
|
126
127
|
annotation_line -= 1
|
127
128
|
end
|
@@ -130,6 +131,10 @@ module RuboCop
|
|
130
131
|
start_line_position(first_comment || node)
|
131
132
|
end
|
132
133
|
|
134
|
+
def inline_comment?(comment)
|
135
|
+
!comment_line?(comment.loc.expression.source_line)
|
136
|
+
end
|
137
|
+
|
133
138
|
def start_line_position(node)
|
134
139
|
buffer.line_range(node.loc.line).begin_pos - 1
|
135
140
|
end
|
@@ -19,8 +19,11 @@ module RuboCop
|
|
19
19
|
# [1, 2, 'a'].append('b')
|
20
20
|
# [1, 2, 'a'].prepend('b')
|
21
21
|
#
|
22
|
-
class ActiveSupportAliases <
|
22
|
+
class ActiveSupportAliases < Base
|
23
|
+
extend AutoCorrector
|
24
|
+
|
23
25
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
26
|
+
RESTRICT_ON_SEND = %i[starts_with? ends_with? append prepend].freeze
|
24
27
|
|
25
28
|
ALIASES = {
|
26
29
|
starts_with?: {
|
@@ -39,29 +42,17 @@ module RuboCop
|
|
39
42
|
|
40
43
|
def on_send(node)
|
41
44
|
ALIASES.each_key do |aliased_method|
|
42
|
-
|
43
|
-
public_send(aliased_method, node)
|
44
|
-
end
|
45
|
-
end
|
45
|
+
next unless public_send(aliased_method, node)
|
46
46
|
|
47
|
-
|
48
|
-
|
47
|
+
preferred_method = ALIASES[aliased_method][:original]
|
48
|
+
message = format(MSG, prefer: preferred_method, current: aliased_method)
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
replacement = ALIASES[method_name.to_sym][:original]
|
53
|
-
corrector.replace(node.loc.selector, replacement.to_s)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
50
|
+
add_offense(node, message: message) do |corrector|
|
51
|
+
next if append(node)
|
58
52
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
message: format(MSG, prefer: ALIASES[method_name][:original],
|
63
|
-
current: method_name)
|
64
|
-
)
|
53
|
+
corrector.replace(node.loc.selector, preferred_method)
|
54
|
+
end
|
55
|
+
end
|
65
56
|
end
|
66
57
|
end
|
67
58
|
end
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
# after_create_commit :log_create_action
|
32
32
|
# after_update_commit :log_update_action
|
33
33
|
#
|
34
|
-
class AfterCommitOverride <
|
34
|
+
class AfterCommitOverride < Base
|
35
35
|
MSG = 'There can only be one `after_*_commit :%<name>s` hook defined for a model.'
|
36
36
|
|
37
37
|
AFTER_COMMIT_CALLBACKS = %i[
|
@@ -59,7 +59,7 @@ module RuboCop
|
|
59
59
|
|
60
60
|
def each_after_commit_callback(class_node)
|
61
61
|
class_send_nodes(class_node).each do |node|
|
62
|
-
yield node if after_commit_callback?(node)
|
62
|
+
yield node if after_commit_callback?(node) && named_callback?(node)
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -78,6 +78,13 @@ module RuboCop
|
|
78
78
|
def after_commit_callback?(node)
|
79
79
|
AFTER_COMMIT_CALLBACKS.include?(node.method_name)
|
80
80
|
end
|
81
|
+
|
82
|
+
def named_callback?(node)
|
83
|
+
name = node.first_argument
|
84
|
+
return false unless name
|
85
|
+
|
86
|
+
name.sym_type?
|
87
|
+
end
|
81
88
|
end
|
82
89
|
end
|
83
90
|
end
|
@@ -16,7 +16,9 @@ module RuboCop
|
|
16
16
|
# class MyController < ActionController::Base
|
17
17
|
# # ...
|
18
18
|
# end
|
19
|
-
class ApplicationController <
|
19
|
+
class ApplicationController < Base
|
20
|
+
extend AutoCorrector
|
21
|
+
|
20
22
|
MSG = 'Controllers should subclass `ApplicationController`.'
|
21
23
|
SUPERCLASS = 'ApplicationController'
|
22
24
|
BASE_PATTERN = '(const (const nil? :ActionController) :Base)'
|
@@ -24,12 +26,6 @@ module RuboCop
|
|
24
26
|
# rubocop:disable Layout/ClassStructure
|
25
27
|
include RuboCop::Cop::EnforceSuperclass
|
26
28
|
# rubocop:enable Layout/ClassStructure
|
27
|
-
|
28
|
-
def autocorrect(node)
|
29
|
-
lambda do |corrector|
|
30
|
-
corrector.replace(node.source_range, self.class::SUPERCLASS)
|
31
|
-
end
|
32
|
-
end
|
33
29
|
end
|
34
30
|
end
|
35
31
|
end
|
@@ -16,7 +16,8 @@ module RuboCop
|
|
16
16
|
# class MyMailer < ActionMailer::Base
|
17
17
|
# # ...
|
18
18
|
# end
|
19
|
-
class ApplicationMailer <
|
19
|
+
class ApplicationMailer < Base
|
20
|
+
extend AutoCorrector
|
20
21
|
extend TargetRailsVersion
|
21
22
|
|
22
23
|
minimum_target_rails_version 5.0
|
@@ -28,12 +29,6 @@ module RuboCop
|
|
28
29
|
# rubocop:disable Layout/ClassStructure
|
29
30
|
include RuboCop::Cop::EnforceSuperclass
|
30
31
|
# rubocop:enable Layout/ClassStructure
|
31
|
-
|
32
|
-
def autocorrect(node)
|
33
|
-
lambda do |corrector|
|
34
|
-
corrector.replace(node.source_range, self.class::SUPERCLASS)
|
35
|
-
end
|
36
|
-
end
|
37
32
|
end
|
38
33
|
end
|
39
34
|
end
|
@@ -16,7 +16,8 @@ module RuboCop
|
|
16
16
|
# class Rails4Model < ActiveRecord::Base
|
17
17
|
# # ...
|
18
18
|
# end
|
19
|
-
class ApplicationRecord <
|
19
|
+
class ApplicationRecord < Base
|
20
|
+
extend AutoCorrector
|
20
21
|
extend TargetRailsVersion
|
21
22
|
|
22
23
|
minimum_target_rails_version 5.0
|
@@ -28,12 +29,6 @@ module RuboCop
|
|
28
29
|
# rubocop:disable Layout/ClassStructure
|
29
30
|
include RuboCop::Cop::EnforceSuperclass
|
30
31
|
# rubocop:enable Layout/ClassStructure
|
31
|
-
|
32
|
-
def autocorrect(node)
|
33
|
-
lambda do |corrector|
|
34
|
-
corrector.replace(node.source_range, self.class::SUPERCLASS)
|
35
|
-
end
|
36
|
-
end
|
37
32
|
end
|
38
33
|
end
|
39
34
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop prevents usage of `"*"` on an Arel::Table column reference.
|
7
|
+
#
|
8
|
+
# Using `arel_table["*"]` causes the outputted string to be a literal
|
9
|
+
# quoted asterisk (e.g. <tt>`my_model`.`*`</tt>). This causes the
|
10
|
+
# database to look for a column named <tt>`*`</tt> (or `"*"`) as opposed
|
11
|
+
# to expanding the column list as one would likely expect.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# # bad
|
15
|
+
# MyTable.arel_table["*"]
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# MyTable.arel_table[Arel.star]
|
19
|
+
#
|
20
|
+
class ArelStar < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
23
|
+
MSG = 'Use `Arel.star` instead of `"*"` for expanded column lists.'
|
24
|
+
|
25
|
+
RESTRICT_ON_SEND = %i[[]].freeze
|
26
|
+
|
27
|
+
def_node_matcher :star_bracket?, <<~PATTERN
|
28
|
+
(send {const (send _ :arel_table)} :[] $(str "*"))
|
29
|
+
PATTERN
|
30
|
+
|
31
|
+
def on_send(node)
|
32
|
+
return unless (star = star_bracket?(node))
|
33
|
+
|
34
|
+
add_offense(star) do |corrector|
|
35
|
+
corrector.replace(star.loc.expression, 'Arel.star')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -13,23 +13,21 @@ module RuboCop
|
|
13
13
|
# # good
|
14
14
|
# assert_not x
|
15
15
|
#
|
16
|
-
class AssertNot <
|
16
|
+
class AssertNot < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
17
19
|
MSG = 'Prefer `assert_not` over `assert !`.'
|
20
|
+
RESTRICT_ON_SEND = %i[assert].freeze
|
18
21
|
|
19
22
|
def_node_matcher :offensive?, '(send nil? :assert (send ... :!) ...)'
|
20
23
|
|
21
24
|
def on_send(node)
|
22
|
-
|
23
|
-
end
|
25
|
+
return unless offensive?(node)
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
+
add_offense(node) do |corrector|
|
28
|
+
expression = node.loc.expression
|
27
29
|
|
28
|
-
|
29
|
-
corrector.replace(
|
30
|
-
expression,
|
31
|
-
corrected_source(expression.source)
|
32
|
-
)
|
30
|
+
corrector.replace(expression, corrected_source(expression.source))
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
# This cop looks for `attribute` class methods that specify a `:default` option
|
7
|
+
# which value is an array, string literal or method call without a block.
|
8
|
+
# It will accept all other values, such as string, symbol, integer and float literals
|
9
|
+
# as well as constants.
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # bad
|
13
|
+
# class User < ApplicationRecord
|
14
|
+
# attribute :confirmed_at, :datetime, default: Time.zone.now
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# class User < ApplicationRecord
|
19
|
+
# attribute :confirmed_at, :datetime, default: -> { Time.zone.now }
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # bad
|
23
|
+
# class User < ApplicationRecord
|
24
|
+
# attribute :roles, :string, array: true, default: []
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# class User < ApplicationRecord
|
29
|
+
# attribute :roles, :string, array: true, default: -> { [] }
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # bad
|
33
|
+
# class User < ApplicationRecord
|
34
|
+
# attribute :configuration, default: {}
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# # good
|
38
|
+
# class User < ApplicationRecord
|
39
|
+
# attribute :configuration, default: -> { {} }
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # good
|
43
|
+
# class User < ApplicationRecord
|
44
|
+
# attribute :role, :string, default: :customer
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# # good
|
48
|
+
# class User < ApplicationRecord
|
49
|
+
# attribute :activated, :boolean, default: false
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# # good
|
53
|
+
# class User < ApplicationRecord
|
54
|
+
# attribute :login_count, :integer, default: 0
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# # good
|
58
|
+
# class User < ApplicationRecord
|
59
|
+
# FOO = 123
|
60
|
+
# attribute :custom_attribute, :integer, default: FOO
|
61
|
+
# end
|
62
|
+
class AttributeDefaultBlockValue < Base
|
63
|
+
extend AutoCorrector
|
64
|
+
|
65
|
+
MSG = 'Pass method in a block to `:default` option.'
|
66
|
+
RESTRICT_ON_SEND = %i[attribute].freeze
|
67
|
+
TYPE_OFFENDERS = %i[send array hash].freeze
|
68
|
+
|
69
|
+
def_node_matcher :default_attribute, <<~PATTERN
|
70
|
+
(send nil? :attribute _ ?_ (hash <$#attribute ...>))
|
71
|
+
PATTERN
|
72
|
+
|
73
|
+
def_node_matcher :attribute, '(pair (sym :default) $_)'
|
74
|
+
|
75
|
+
def on_send(node)
|
76
|
+
default_attribute(node) do |attribute|
|
77
|
+
value = attribute.children.last
|
78
|
+
return unless TYPE_OFFENDERS.any?(value.type)
|
79
|
+
|
80
|
+
add_offense(value) do |corrector|
|
81
|
+
expression = default_attribute(node).children.last
|
82
|
+
|
83
|
+
corrector.replace(value, "-> { #{expression.source} }")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|