Skip to content

Rails/ReflectionClassName doesn't match relations that have an optional scope proc or lambda #332

Closed
@bubaflub

Description

At work we're upgrading from Rails 5.0 to 5.1 and I just noticed some deprecation warnings:

DEPRECATION WARNING: Passing a class to the `class_name` is deprecated and will raise an ArgumentError in Rails 5.2. It eagerloads more classes than necessary and potentially creates circular dependencies. Please pass the class name as a string: `has_many :redacted, class_name: 'redacted'` (called from <class:Redacted> at redacted.rb:36)

This was surprising since I thought we had fixed all of these with the Rails/ReflectionClassName rubocop. On closer inspection the ones that weren't flagged by the Rails/ReflectionClassName cop all had an optional second parameter that was a proc or lambda that acts as a scope on the relation. See https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-belongs_to-label-Scopes for more details on what that scope does.

Deleting the proc or lambda caused Rails/ReflectionClassName to correctly flag these relations.


Expected behavior

Expected Rails/ReflectionClassName to warn me about relations in my models that had both:

  • a proc or lambda scope 2nd parameter
  • a String for the class_name option

Actual behavior

Rails/ReflectionClassName didn't warn about these lines.

Steps to reproduce the problem

Files:

Gemfile gem 'rubocop-rails'
Gemfile.lock
GEM
  specs:
    activesupport (5.1.7)
      concurrent-ruby (~> 1.0, >= 1.0.2)
      i18n (>= 0.7, < 2)
      minitest (~> 5.1)
      tzinfo (~> 1.1)
    ast (2.4.1)
    concurrent-ruby (1.1.6)
    i18n (1.8.2)
      concurrent-ruby (~> 1.0)
    minitest (5.14.1)
    parallel (1.19.2)
    parser (2.7.1.4)
      ast (~> 2.4.1)
    rack (2.2.3)
    rainbow (3.0.0)
    regexp_parser (1.7.1)
    rexml (3.2.4)
    rubocop (0.89.1)
      parallel (~> 1.10)
      parser (>= 2.7.1.1)
      rainbow (>= 2.2.2, < 4.0)
      regexp_parser (>= 1.7)
      rexml
      rubocop-ast (>= 0.3.0, < 1.0)
      ruby-progressbar (~> 1.7)
      unicode-display_width (>= 1.4.0, < 2.0)
    rubocop-ast (0.3.0)
      parser (>= 2.7.1.4)
    rubocop-rails (2.5.2)
      activesupport
      rack (>= 1.1)
      rubocop (>= 0.72.0)
    ruby-progressbar (1.10.1)
    thread_safe (0.3.6)
    tzinfo (1.2.7)
      thread_safe (~> 0.1)
    unicode-display_width (1.7.0)

PLATFORMS
ruby

DEPENDENCIES
rubocop-rails

BUNDLED WITH
1.16.6

.rubocop.yml
require:
  - rubocop-rails

Rails:
Enabled: true

app/models/bar.rb
class Bar
end
app/models/foo.rb
class Foo < ActiveRecord::Base
  belongs_to :bar_1, class_name: 'Bar'
  belongs_to :bar_2, class_name: Bar
  belongs_to :bar_3, -> { }, class_name: 'Bar'
  belongs_to :bar_4, -> { }, class_name: Bar
end

rubocop output:

bundle exec rubocop --only Rails/ReflectionClassName app/models/foo.rb
The following cops were added to RuboCop, but are not configured. ...
...
Inspecting 1 file
C

Offenses:

app/models/foo.rb:3:22: C: Rails/ReflectionClassName: Use a string value for class_name.
  belongs_to :bar_2, class_name: Bar
                     ^^^^^^^^^^^^^^^

1 file inspected, 1 offense detected

I expected the cop to flag both line 3 and line 5 but it doesn't because it won't match against a relation that has a 2nd pararmeter.

RuboCop version

bob@MacBook-Pro truelink % bundle exec rubocop -V
0.89.1 (using Parser 2.7.1.4, rubocop-ast 0.3.0, running on ruby 2.5.8 x86_64-darwin19)

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions