Skip to content

Commit 2a68054

Browse files
committed
[Fix #757] Fix a false positive for Rails/ReflectionClassName
Fixes #757. This PR fixes a false positive for `Rails/ReflectionClassName` when using Ruby 3.1's hash shorthand syntax.
1 parent 6fc6d22 commit 2a68054

File tree

4 files changed

+67
-0
lines changed

4 files changed

+67
-0
lines changed

.rubocop_todo.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ InternalAffairs/NodeDestructuring:
1111
Exclude:
1212
- 'lib/rubocop/cop/rails/environment_comparison.rb'
1313
- 'lib/rubocop/cop/rails/exit.rb'
14+
- 'lib/rubocop/cop/rails/reflection_class_name.rb'
1415
- 'lib/rubocop/cop/rails/relative_date_constant.rb'
1516
- 'lib/rubocop/cop/rails/time_zone.rb'
1617

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#757](https://github.com/rubocop/rubocop-rails/issues/757): Fix a false positive for `Rails/ReflectionClassName` when using Ruby 3.1's hash shorthand syntax. ([@koic][])

lib/rubocop/cop/rails/reflection_class_name.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,29 @@ class ReflectionClassName < Base
3434

3535
def on_send(node)
3636
association_with_reflection(node) do |reflection_class_name|
37+
return if reflection_class_name.value.send_type? && reflection_class_name.value.receiver.nil?
38+
return if reflection_class_name.value.lvar_type? && str_assigned?(reflection_class_name)
39+
3740
add_offense(reflection_class_name.loc.expression)
3841
end
3942
end
4043

4144
private
4245

46+
def str_assigned?(reflection_class_name)
47+
lvar = reflection_class_name.value.source
48+
49+
reflection_class_name.ancestors.each do |nodes|
50+
return true if nodes.each_child_node(:lvasgn).detect do |node|
51+
lhs, rhs = *node
52+
53+
lhs.to_s == lvar && ALLOWED_REFLECTION_CLASS_TYPES.include?(rhs.type)
54+
end
55+
end
56+
57+
false
58+
end
59+
4360
def reflection_class_value?(class_value)
4461
if class_value.send_type?
4562
!class_value.method?(:to_s) || class_value.receiver&.const_type?

spec/rubocop/cop/rails/reflection_class_name_spec.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,52 @@
8080
belongs_to :account, class_name: :Account
8181
RUBY
8282
end
83+
84+
it 'registers an offense when parameter value is a local variable assigned a constant' do
85+
expect_offense(<<~RUBY)
86+
class_name = Account
87+
88+
has_many :accounts, class_name: class_name
89+
^^^^^^^^^^^^^^^^^^^^^^ Use a string value for `class_name`.
90+
RUBY
91+
end
92+
93+
it 'does not register an offense when parameter value is a local variable assigned a string' do
94+
expect_no_offenses(<<~RUBY)
95+
class_name = 'Account'
96+
97+
has_many :accounts, class_name: class_name
98+
RUBY
99+
end
100+
101+
it 'does not register an offense when parameter value is a method call' do
102+
expect_no_offenses(<<~RUBY)
103+
has_many :accounts, class_name: class_name
104+
RUBY
105+
end
106+
107+
context 'Ruby >= 3.1', :ruby31 do
108+
it 'registers an offense when shorthand syntax value is a local variable assigned a constant' do
109+
expect_offense(<<~RUBY)
110+
class_name = Account
111+
112+
has_many :accounts, class_name:
113+
^^^^^^^^^^^ Use a string value for `class_name`.
114+
RUBY
115+
end
116+
117+
it 'does not register an offense when shorthand syntax value is a local variable assigned a string' do
118+
expect_no_offenses(<<~RUBY)
119+
class_name = 'Account'
120+
121+
has_many :accounts, class_name:
122+
RUBY
123+
end
124+
125+
it 'does not register an offense when shorthand syntax value is a local variable assigned a method call' do
126+
expect_no_offenses(<<~RUBY)
127+
has_many :accounts, class_name:
128+
RUBY
129+
end
130+
end
83131
end

0 commit comments

Comments
 (0)