-
-
Notifications
You must be signed in to change notification settings - Fork 284
Description
Expected behavior
In conservative mode, Rails/UniqBeforePluck should only flag calls to pluck on model class constants (e.g., User, Post), not on arbitrary constants that happen to be arrays or other non-ActiveRecord objects.
From the documentation:
When the EnforcedStyle is conservative (the default) then only calls to pluck on a constant (i.e. a model class) before uniq are added as offenses.
Actual behavior
The cop flags any constant, including plain Ruby array constants. The autocorrection then produces broken code because distinct is an ActiveRecord method that doesn't exist on plain arrays.
Steps to reproduce the problem
# example.rb
DEFAULT_RULES = [
{ resource_type: 'Study', action: :read },
{ resource_type: 'Study', action: :write },
{ resource_type: 'Candidate', action: :read }
].freeze
resource_types = DEFAULT_RULES.pluck(:resource_type).uniqRun with:
rubocop --only Rails/UniqBeforePluck example.rbOutput:
example.rb:8:50: C: Rails/UniqBeforePluck: Use distinct before pluck.
resource_types = DEFAULT_RULES.pluck(:resource_type).uniq
^^^^
After autocorrection (rubocop -A):
resource_types = DEFAULT_RULES.distinct.pluck(:resource_type)This code fails at runtime with:
NoMethodError: undefined method 'distinct' for an instance of Array
Root cause
The conservative mode check in the cop uses:
pluck_node.receiver&.const_type?This returns true for any constant, not just model classes. The cop cannot distinguish between:
User(a model class wheredistinctis valid)DEFAULT_RULES(an Array constant wheredistinctdoesn't exist)
Suggested fix
Either:
- Update the documentation to reflect that conservative mode flags all constants (not just model classes)
- Or improve the detection to only flag constants that are likely ActiveRecord models (e.g., by checking inheritance or using heuristics)
- Or mark
SafeAutoCorrect: falseis already set, but consider adding a note that this autocorrection can produce broken code for non-AR constants
RuboCop version
$ bundle exec rubocop -V
1.81.7 (using Parser 3.3.10.0, Prism 1.6.0, rubocop-ast 1.48.0, analyzing as Ruby 3.4, running on ruby 3.4.7) [arm64-darwin24]
- rubocop-rails 2.34.1