Skip to content

Commit

Permalink
Merge pull request #6704 from Bhacaz/add_cop_relfection_class_name_st…
Browse files Browse the repository at this point in the history
…ring

Added ReflectionClassNameString cop
  • Loading branch information
koic committed Jan 29, 2019
2 parents 4d6d4b6 + 5b8de06 commit 138c232
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,7 @@

### New features

* [#6704](https://github.com/rubocop-hq/rubocop/pull/6704): Add new `Rails/ReflectionClassName` cop. ([@Bhacaz][])
* [#6643](https://github.com/rubocop-hq/rubocop/pull/6643): Support `AllowParenthesesInCamelCaseMethod` option on `Style/MethodCallWithArgsParentheses` `omit_parentheses`. ([@dazuma][])

### Bug fixes
Expand Down Expand Up @@ -3792,3 +3793,4 @@
[@dazuma]: https://github.com/dazuma
[@dischorde]: https://github.com/dischorde
[@mhelmetag]: https://github.com/mhelmetag
[@Bhacaz]: https://github.com/bhacaz
5 changes: 5 additions & 0 deletions config/default.yml
Expand Up @@ -2493,6 +2493,11 @@ Rails/RedundantReceiverInWithOptions:
Enabled: true
VersionAdded: '0.52'

Rails/ReflectionClassName:
Description: 'Use a string for `class_name` option value in the definition of a reflection.'
Enabled: true
VersionAdded: '0.64'

Rails/RefuteMethods:
Description: 'Use `assert_not` methods instead of `refute` methods.'
Enabled: true
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop.rb
Expand Up @@ -592,6 +592,7 @@
require_relative 'rubocop/cop/rails/present'
require_relative 'rubocop/cop/rails/read_write_attribute'
require_relative 'rubocop/cop/rails/redundant_receiver_in_with_options'
require_relative 'rubocop/cop/rails/reflection_class_name'
require_relative 'rubocop/cop/rails/refute_methods'
require_relative 'rubocop/cop/rails/relative_date_constant'
require_relative 'rubocop/cop/rails/request_referer'
Expand Down
38 changes: 38 additions & 0 deletions lib/rubocop/cop/rails/reflection_class_name.rb
@@ -0,0 +1,38 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Rails
# This cop checks if the value of the option `class_name`, in
# the definition of a reflection is a string.
#
# @example
# # bad
# has_many :accounts, class_name: Account
# has_many :accounts, class_name: Account.name
#
# # good
# has_many :accounts, class_name: 'Account'
class ReflectionClassName < Cop
MSG = 'Use a string has value for a class_name.'.freeze

def_node_matcher :association_with_options?, <<-PATTERN
(send nil? {:has_many :has_one :belongs_to} _ (hash $...))
PATTERN

def_node_search :reflection_class_name, <<-PATTERN
(pair (sym :class_name) !str)
PATTERN

def on_send(node)
return unless association_with_options?(node)

reflection_class_name = reflection_class_name(node).first
return unless reflection_class_name

add_offense(node, location: reflection_class_name.loc.expression)
end
end
end
end
end
1 change: 1 addition & 0 deletions manual/cops.md
Expand Up @@ -368,6 +368,7 @@ In the following section you find all available cops:
* [Rails/Present](cops_rails.md#railspresent)
* [Rails/ReadWriteAttribute](cops_rails.md#railsreadwriteattribute)
* [Rails/RedundantReceiverInWithOptions](cops_rails.md#railsredundantreceiverinwithoptions)
* [Rails/ReflectionClassName](cops_rails.md#railsreflectionclassname)
* [Rails/RefuteMethods](cops_rails.md#railsrefutemethods)
* [Rails/RelativeDateConstant](cops_rails.md#railsrelativedateconstant)
* [Rails/RequestReferer](cops_rails.md#railsrequestreferer)
Expand Down
20 changes: 20 additions & 0 deletions manual/cops_rails.md
Expand Up @@ -1572,6 +1572,26 @@ with_options options: false do |merger|
end
```

## Rails/ReflectionClassName

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

This cop checks if the value of the option `class_name`, in
the definition of a reflection is a string.

### Examples

```ruby
# bad
has_many :accounts, class_name: Account
has_many :accounts, class_name: Account.name

# good
has_many :accounts, class_name: 'Account'
```

## Rails/RefuteMethods

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

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

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

context "registers an offense when using `foreign_key: 'account_id'`" do
it 'has_many' do
expect_offense(<<-RUBY.strip_indent)
has_many :accounts, class_name: Account, foreign_key: :account_id
^^^^^^^^^^^^^^^^^^^ Use a string has value for a class_name.
RUBY
end

it '.name' do
expect_offense(<<-RUBY.strip_indent)
has_many :accounts, class_name: Account.name
^^^^^^^^^^^^^^^^^^^^^^^^ Use a string has value for a class_name.
RUBY
end

it 'has_one' do
expect_offense(<<-RUBY.strip_indent)
has_one :account, class_name: Account
^^^^^^^^^^^^^^^^^^^ Use a string has value for a class_name.
RUBY
end

it 'belongs_to' do
expect_offense(<<-RUBY.strip_indent)
belongs_to :account, class_name: Account
^^^^^^^^^^^^^^^^^^^ Use a string has value for a class_name.
RUBY
end
end

it 'does not register an offense when using `foreign_key :account_id`' do
expect_no_offenses(<<-RUBY.strip_indent)
has_many :accounts, class_name: 'Account', foreign_key: :account_id
has_one :account, class_name: 'Account'
belongs_to :account, class_name: 'Account'
RUBY
end
end

0 comments on commit 138c232

Please sign in to comment.