Skip to content

Commit

Permalink
[Fix #106] Make Rails/ReflectionClassName aware of the use of strin…
Browse files Browse the repository at this point in the history
…g with `to_s`

Follow #469

Fixes #106.

This PR makes `Rails/ReflectionClassName` aware of the use of string with `to_s`.
  • Loading branch information
koic committed Apr 28, 2021
1 parent 66d1a6b commit 1d6317b
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
* [#403](https://github.com/rubocop/rubocop-rails/pull/403): Mark `Rails/WhereEquals` as unsafe auto-correction. ([@koic][])
* [#379](https://github.com/rubocop/rubocop-rails/issues/379): Mark `Rails/DynamicFindBy` as unsafe. ([@koic][])
* [#106](https://github.com/rubocop/rubocop-rails/issues/106): Mark `Rails/ReflectionClassName` as unsafe. ([@koic][])
* [#106](https://github.com/rubocop/rubocop-rails/issues/106): Make `Rails/ReflectionClassName` aware of the use of string with `to_s`. ([@koic][])
* [#456](https://github.com/rubocop/rubocop-rails/pull/456): Drop Ruby 2.4 support. ([@koic][])
* [#462](https://github.com/rubocop/rubocop-rails/pull/462): Require RuboCop 1.7 or higher. ([@koic][])

Expand Down
13 changes: 12 additions & 1 deletion lib/rubocop/cop/rails/reflection_class_name.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module Rails
class ReflectionClassName < Base
MSG = 'Use a string value for `class_name`.'
RESTRICT_ON_SEND = %i[has_many has_one belongs_to].freeze
ALLOWED_REFLECTION_CLASS_TYPES = %i[dstr str sym].freeze

def_node_matcher :association_with_reflection, <<~PATTERN
(send nil? {:has_many :has_one :belongs_to} _ _ ?
Expand All @@ -26,14 +27,24 @@ class ReflectionClassName < Base
PATTERN

def_node_matcher :reflection_class_name, <<~PATTERN
(pair (sym :class_name) [!dstr !str !sym])
(pair (sym :class_name) #reflection_class_value?)
PATTERN

def on_send(node)
association_with_reflection(node) do |reflection_class_name|
add_offense(reflection_class_name.loc.expression)
end
end

private

def reflection_class_value?(class_value)
if class_value.send_type?
!class_value.method?(:to_s) || class_value.receiver.const_type?
else
!ALLOWED_REFLECTION_CLASS_TYPES.include?(class_value.type)
end
end
end
end
end
Expand Down
13 changes: 13 additions & 0 deletions spec/rubocop/cop/rails/reflection_class_name_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
RUBY
end

it '.to_s' do
expect_offense(<<~RUBY)
has_many :accounts, class_name: Account.to_s
^^^^^^^^^^^^^^^^^^^^^^^^ Use a string value for `class_name`.
RUBY
end

it 'has_one' do
expect_offense(<<~RUBY)
has_one :account, class_name: Account
Expand Down Expand Up @@ -46,6 +53,12 @@
RUBY
end

it 'does not register an offense when using `class_name: do_something.to_s`' do
expect_no_offenses(<<~'RUBY')
has_many :accounts, class_name: do_something.to_s
RUBY
end

it 'does not register an offense when using `foreign_key :account_id`' do
expect_no_offenses(<<~RUBY)
has_many :accounts, class_name: 'Account', foreign_key: :account_id
Expand Down

0 comments on commit 1d6317b

Please sign in to comment.