Skip to content

Commit b59cecf

Browse files
authored
Merge pull request #1348 from Earlopain/enum-syntax-non-literal
[Fix #1343] False negatives for `Rails/EnumSyntax`
2 parents 5c8b114 + dbdee93 commit b59cecf

File tree

3 files changed

+40
-17
lines changed

3 files changed

+40
-17
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#1343](https://github.com/rubocop/rubocop-rails/issues/1343): Fix false negatives for `Rails/EnumSyntax` for non-literal mappings. ([@earlopain][])

lib/rubocop/cop/rails/enum_syntax.rb

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ class EnumSyntax < Base
2424
MSG = 'Enum defined with keyword arguments in `%<enum>s` enum declaration. Use positional arguments instead.'
2525
MSG_OPTIONS = 'Enum defined with deprecated options in `%<enum>s` enum declaration. Remove the `_` prefix.'
2626
RESTRICT_ON_SEND = %i[enum].freeze
27-
OPTION_NAMES = %w[prefix suffix scopes default].freeze
27+
28+
# From https://github.com/rails/rails/blob/v7.2.1/activerecord/lib/active_record/enum.rb#L231
29+
OPTION_NAMES = %w[prefix suffix scopes default instance_methods].freeze
30+
UNDERSCORED_OPTION_NAMES = OPTION_NAMES.map { |option| "_#{option}" }.freeze
2831

2932
def_node_matcher :enum?, <<~PATTERN
3033
(send nil? :enum (hash $...))
@@ -34,14 +37,6 @@ class EnumSyntax < Base
3437
(send nil? :enum $_ ${array hash} $_)
3538
PATTERN
3639

37-
def_node_matcher :enum_values, <<~PATTERN
38-
(pair $_ ${array hash})
39-
PATTERN
40-
41-
def_node_matcher :enum_options, <<~PATTERN
42-
(pair $_ $_)
43-
PATTERN
44-
4540
def on_send(node)
4641
check_and_correct_keyword_args(node)
4742
check_enum_options(node)
@@ -52,20 +47,17 @@ def on_send(node)
5247
def check_and_correct_keyword_args(node)
5348
enum?(node) do |pairs|
5449
pairs.each do |pair|
55-
key, values = enum_values(pair)
56-
next unless key
50+
next if option_key?(pair)
5751

58-
correct_keyword_args(node, key, values, pairs[1..])
52+
correct_keyword_args(node, pair.key, pair.value, pairs[1..])
5953
end
6054
end
6155
end
6256

6357
def check_enum_options(node)
6458
enum_with_options?(node) do |key, _, options|
6559
options.children.each do |option|
66-
name, = enum_options(option)
67-
68-
add_offense(name, message: format(MSG_OPTIONS, enum: enum_name_value(key))) if name.source[0] == '_'
60+
add_offense(option.key, message: format(MSG_OPTIONS, enum: enum_name_value(key))) if option_key?(option)
6961
end
7062
end
7163
end
@@ -107,6 +99,10 @@ def enum_name(elem)
10799
end
108100
end
109101

102+
def option_key?(pair)
103+
UNDERSCORED_OPTION_NAMES.include?(pair.key.source)
104+
end
105+
110106
def correct_options(options)
111107
corrected_options = options.map do |pair|
112108
name = if pair.key.source[0] == '_'

spec/rubocop/cop/rails/enum_syntax_spec.rb

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,32 @@
8282
end
8383
end
8484

85+
context 'when the enum name is underscored' do
86+
it 'registers an offense' do
87+
expect_offense(<<~RUBY)
88+
enum :_key => { active: 0, archived: 1 }, _prefix: true
89+
^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined with keyword arguments in `_key` enum declaration. Use positional arguments instead.
90+
RUBY
91+
92+
expect_correction(<<~RUBY)
93+
enum :_key, { active: 0, archived: 1 }, prefix: true
94+
RUBY
95+
end
96+
end
97+
98+
context 'when the enum value is not a literal' do
99+
it 'registers an offense' do
100+
expect_offense(<<~RUBY)
101+
enum key: %i[foo bar].map.with_index { |v, i| [v, i] }.to_h
102+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined with keyword arguments in `key` enum declaration. Use positional arguments instead.
103+
RUBY
104+
105+
expect_correction(<<~RUBY)
106+
enum :key, %i[foo bar].map.with_index { |v, i| [v, i] }.to_h
107+
RUBY
108+
end
109+
end
110+
85111
it 'autocorrects' do
86112
expect_offense(<<~RUBY)
87113
enum status: { active: 0, archived: 1 }
@@ -95,12 +121,12 @@
95121

96122
it 'autocorrects options too' do
97123
expect_offense(<<~RUBY)
98-
enum status: { active: 0, archived: 1 }, _prefix: true, _suffix: true, _default: :active, _scopes: true
124+
enum status: { active: 0, archived: 1 }, _prefix: true, _suffix: true, _default: :active, _scopes: true, _instance_methods: true
99125
^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined with keyword arguments in `status` enum declaration. Use positional arguments instead.
100126
RUBY
101127

102128
expect_correction(<<~RUBY)
103-
enum :status, { active: 0, archived: 1 }, prefix: true, suffix: true, default: :active, scopes: true
129+
enum :status, { active: 0, archived: 1 }, prefix: true, suffix: true, default: :active, scopes: true, instance_methods: true
104130
RUBY
105131
end
106132
end

0 commit comments

Comments
 (0)