New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix #3723] Add new Rails/EnumUniqueness cop. #3724

Merged
merged 1 commit into from Nov 21, 2016

Conversation

Projects
None yet
2 participants
@olliebennett
Contributor

olliebennett commented Nov 16, 2016

A new Rails/EnumUniqueness cop which identifies any (presumably accidental) usage of duplicate enum value definitions.

# bad
enum status: { active: 4, archived: 4 }

More details in issue #3723.

This is functional (and tested), but probably not the best approach. I'm open to feedback around any shortcuts / simplifications / alternative approaches / other cops to take inspiration from - specifically around my (somewhat clunky) handling of args passed to enum via RuboCop::Node. I'm also open to alternative names for this cop.


Before submitting the PR make sure the following are checked:

  • Wrote good commit messages.
  • Commit message starts with [Fix #issue-number] (if the related issue exists).
  • Used the same coding conventions as the rest of the project.
  • Feature branch is up-to-date with master (if not - rebase it).
  • Squashed related commits together.
  • Added tests.
  • Added an entry to the Changelog if the new code introduces user-observable changes. See changelog entry format.
  • All tests are passing.
  • The new code doesn't generate RuboCop offenses.
  • The PR relates to only one subject with a clear title
    and description in grammatically correct, complete sentences.
  • Updated cop documentation with rake generate_cops_documentation (required only when you've added a new cop or changed the configuration/documentation of an existing cop).
Show outdated Hide outdated spec/rubocop/cop/rails/enum_uniqueness_spec.rb
expect(cop.messages).to be_empty
end
it 'does not crash given additional enum configuration' do

This comment has been minimized.

@bbatsov

bbatsov Nov 21, 2016

Collaborator

I'd reword this to "does not register an offense when given...". It's a bit odd to have tests testing that something doesn't crash IMO. :-)

@bbatsov

bbatsov Nov 21, 2016

Collaborator

I'd reword this to "does not register an offense when given...". It's a bit odd to have tests testing that something doesn't crash IMO. :-)

Show outdated Hide outdated lib/rubocop/cop/rails/enum_uniqueness.rb
module RuboCop
module Cop
module Rails
# This cop looks for duplicate values in enum declarations

This comment has been minimized.

@bbatsov

bbatsov Nov 21, 2016

Collaborator

This sentence should end with a ..

@bbatsov

bbatsov Nov 21, 2016

Collaborator

This sentence should end with a ..

Show outdated Hide outdated lib/rubocop/cop/rails/enum_uniqueness.rb
# enum status: { active: 0, archived: 1 }
#
# # good
# enum status: [ :active, :archived ]

This comment has been minimized.

@bbatsov

bbatsov Nov 21, 2016

Collaborator

Remove the spaces inside [].

@bbatsov

bbatsov Nov 21, 2016

Collaborator

Remove the spaces inside [].

@bbatsov

This comment has been minimized.

Show comment
Hide comment
@bbatsov

bbatsov Nov 21, 2016

Collaborator

Apart from my small remarks - this has to be rebased.

Collaborator

bbatsov commented Nov 21, 2016

Apart from my small remarks - this has to be rebased.

[Fix #3723] Add new Rails/EnumUniqueness cop
This introduces a new cop which identifies any usage of duplicate values in hash-syntax enum definitions in Rails models.

For example, the following can lead to an ambiguous "status" for the model:
enum status: { active: 4, archived: 4 }

An enum in Rails can be defined either as an array or a hash with specific integer keys defined.
See: http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html

enum status: [ :active, :archived ]
enum status: { active: 0, archived: 1 }

With the latter syntax, it's possible to accidentally specify duplicate keys:

enum status: { active: 4, archived: 4 }

Bugs resulting from this can be hard to identify.
@olliebennett

This comment has been minimized.

Show comment
Hide comment
@olliebennett

olliebennett Nov 21, 2016

Contributor

Thanks Bozhidar; you're the human Rubocop I can only strive to be! 😉

I've addressed all remarks and rebased again. Thanks for reviewing.

Contributor

olliebennett commented Nov 21, 2016

Thanks Bozhidar; you're the human Rubocop I can only strive to be! 😉

I've addressed all remarks and rebased again. Thanks for reviewing.

@bbatsov bbatsov merged commit 0f14012 into rubocop-hq:master Nov 21, 2016

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

@olliebennett olliebennett deleted the olliebennett:feature/enum-uniqueness branch Nov 21, 2016

@bbatsov

This comment has been minimized.

Show comment
Hide comment
@bbatsov

bbatsov Nov 21, 2016

Collaborator

Btw, I'm sure if this happens or not, but I'm guessing another problem we can check for is duplicate elements in an array enum - e.g. enum status: [:ala, :bala, :ala].

Collaborator

bbatsov commented Nov 21, 2016

Btw, I'm sure if this happens or not, but I'm guessing another problem we can check for is duplicate elements in an array enum - e.g. enum status: [:ala, :bala, :ala].

@olliebennett

This comment has been minimized.

Show comment
Hide comment
@olliebennett

olliebennett Nov 21, 2016

Contributor

Good point. Rails at least catches that (albeit indirectly and confusingly) as follows:

/Users/ollie/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/enum.rb:187:in `detect_enum_conflict!': You tried to define an enum named "status" on the model "User", but this will generate a instance method "ala?", which is already defined by another enum. (ArgumentError)

It would make sense to catch at Rubocop stage though. Will enhance this cop when I get a moment.

Contributor

olliebennett commented Nov 21, 2016

Good point. Rails at least catches that (albeit indirectly and confusingly) as follows:

/Users/ollie/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activerecord-4.2.7.1/lib/active_record/enum.rb:187:in `detect_enum_conflict!': You tried to define an enum named "status" on the model "User", but this will generate a instance method "ala?", which is already defined by another enum. (ArgumentError)

It would make sense to catch at Rubocop stage though. Will enhance this cop when I get a moment.

@olliebennett

This comment has been minimized.

Show comment
Hide comment
@olliebennett

olliebennett Nov 21, 2016

Contributor

^ I got a moment.

Contributor

olliebennett commented Nov 21, 2016

^ I got a moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment