Skip to content

Commit

Permalink
[Fix rubocop#78] Create HashEnum Cop
Browse files Browse the repository at this point in the history
  • Loading branch information
Bruno Vezoli authored and brunvez committed Jul 24, 2019
1 parent cdb7330 commit a5ea0b2
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,10 @@

## master (unreleased)

### New features

* [#78](https://github.com/rubocop-hq/rubocop-rails/issues/78): Add new `Rails/HashEnum` cop. ([@fedeagripa][], [@brunvez][], [@santib][])

### Bug fixes

* [#53](https://github.com/rubocop-hq/rubocop-rails/issues/53): Fix a false positive for `Rails/SaveBang` when implicitly return using finder method and creation method connected by `||`. ([@koic][])
Expand Down Expand Up @@ -47,3 +51,6 @@
[@buehmann]: https://github.com/buehmann
[@anthony-robin]: https://github.com/anthony-robin
[@rmm5t]: https://github.com/rmm5t
[@fedeagripa]: https://github.com/fedeagripa
[@brunvez]: https://github.com/brunvez
[@santib]: https://github.com/santib
7 changes: 7 additions & 0 deletions config/default.yml
Expand Up @@ -213,6 +213,13 @@ Rails/HasManyOrHasOneDependent:
Include:
- app/models/**/*.rb

Rails/HashEnum:
Description: 'Prefer hash syntax over array syntax when defining enums'
Enabled: true
VersionAdded: '0.74'
Include:
- app/models/**/*.rb

Rails/HelperInstanceVariable:
Description: 'Do not use instance variables in helpers'
Enabled: true
Expand Down
36 changes: 36 additions & 0 deletions lib/rubocop/cop/rails/hash_enum.rb
@@ -0,0 +1,36 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Rails
# This cop looks for enums written with array syntax.
#
# When using array syntax adding an element in a
# position other than the last causes all previous
# definitions to shift. Explicitly specifying the
# value for each key prevents this from happening.
#
# @example
# # bad
# enum status: [:active, :archived]
#
# # good
# enum status: { active: 0, archived: 1 }
#
class HashEnum < Cop
MSG = 'Enum defined as an array found in `%<enum>s` enum declaration. '\
'Use hash syntax instead.'

def_node_matcher :enum_with_array?, <<~PATTERN
(send nil? :enum (hash (pair (_ $_) array)))
PATTERN

def on_send(node)
enum_with_array?(node) do |name, _args|
add_offense(node, message: format(MSG, enum: name))
end
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/rails_cops.rb
Expand Up @@ -25,6 +25,7 @@
require_relative 'rails/find_each'
require_relative 'rails/has_and_belongs_to_many'
require_relative 'rails/has_many_or_has_one_dependent'
require_relative 'rails/hash_enum'
require_relative 'rails/helper_instance_variable'
require_relative 'rails/http_positional_arguments'
require_relative 'rails/http_status'
Expand Down
1 change: 1 addition & 0 deletions manual/cops.md
Expand Up @@ -24,6 +24,7 @@
* [Rails/FindEach](cops_rails.md#railsfindeach)
* [Rails/HasAndBelongsToMany](cops_rails.md#railshasandbelongstomany)
* [Rails/HasManyOrHasOneDependent](cops_rails.md#railshasmanyorhasonedependent)
* [Rails/HashEnum](cops_rails.md#railshashenum)
* [Rails/HelperInstanceVariable](cops_rails.md#railshelperinstancevariable)
* [Rails/HttpPositionalArguments](cops_rails.md#railshttppositionalarguments)
* [Rails/HttpStatus](cops_rails.md#railshttpstatus)
Expand Down
24 changes: 24 additions & 0 deletions manual/cops_rails.md
Expand Up @@ -896,6 +896,30 @@ Include | `app/models/**/*.rb` | Array

* [https://rails.rubystyle.guide#has_many-has_one-dependent-option](https://rails.rubystyle.guide#has_many-has_one-dependent-option)

## Rails/HashEnum

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
--- | --- | --- | --- | ---
Enabled | Yes | No | 0.74 | -

This cop looks for enums written with array syntax

### Examples

```ruby
# bad
enum status: [:active, :archived]

# good
enum status: { active: 0, archived: 1 }
```

### Configurable attributes

Name | Default value | Configurable values
--- | --- | ---
Include | `app/models/**/*.rb` | Array

## Rails/HelperInstanceVariable

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
Expand Down
60 changes: 60 additions & 0 deletions spec/rubocop/cop/rails/hash_enum_spec.rb
@@ -0,0 +1,60 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Rails::HashEnum do
subject(:cop) { described_class.new(config) }

let(:config) { RuboCop::Config.new }

context 'when array syntax is used' do
context 'with %i[] syntax' do
it 'registers an offense' do
expect_offense(<<~RUBY)
enum status: %i[active archived]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead.
RUBY
end
end

context 'with %w[] syntax' do
it 'registers an offense' do
expect_offense(<<~RUBY)
enum status: %w[active archived]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead.
RUBY
end
end

context 'with %i() syntax' do
it 'registers an offense' do
expect_offense(<<~RUBY)
enum status: %i(active archived)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead.
RUBY
end
end

context 'with %w() syntax' do
it 'registers an offense' do
expect_offense(<<~RUBY)
enum status: %w(active archived)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead.
RUBY
end
end

context 'with [] syntax' do
it 'registers an offense' do
expect_offense(<<~RUBY)
enum status: [:active, :archived]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Enum defined as an array found in `status` enum declaration. Use hash syntax instead.
RUBY
end
end
end

context 'when hash syntax is used' do
it 'does not register an offense' do
expect_no_offenses('enum status: { active: 0, archived: 1 }')
end
end
end

0 comments on commit a5ea0b2

Please sign in to comment.