Class: RuboCop::Cop::Rails::UniqBeforePluck

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
ConfigurableEnforcedStyle, RangeHelp
Defined in:
lib/rubocop/cop/rails/uniq_before_pluck.rb

Overview

Prefer using ‘distinct` before `pluck` instead of `uniq` after `pluck`.

The use of distinct before pluck is preferred because it executes by the database.

This cop has two different enforcement modes. 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.

When the EnforcedStyle is ‘aggressive` then all calls to `pluck` before distinct are added as offenses. This may lead to false positives as the cop cannot distinguish between calls to `pluck` on an ActiveRecord::Relation vs a call to pluck on an ActiveRecord::Associations::CollectionProxy.

Examples:

EnforcedStyle: conservative (default)

# bad - redundantly fetches duplicate values
Album.pluck(:band_name).uniq

# good
Album.distinct.pluck(:band_name)

EnforcedStyle: aggressive

# bad - redundantly fetches duplicate values
Album.pluck(:band_name).uniq

# bad - redundantly fetches duplicate values
Album.where(year: 1985).pluck(:band_name).uniq

# bad - redundantly fetches duplicate values
customer.favourites.pluck(:color).uniq

# good
Album.distinct.pluck(:band_name)
Album.distinct.where(year: 1985).pluck(:band_name)
customer.favourites.distinct.pluck(:color)

Constant Summary collapse

MSG =
'Use `distinct` before `pluck`.'
RESTRICT_ON_SEND =
%i[uniq].freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object



57
58
59
60
61
62
63
64
65
# File 'lib/rubocop/cop/rails/uniq_before_pluck.rb', line 57

def on_send(node)
  uniq_before_pluck(node) do |uniq_node, pluck_node|
    next if style == :conservative && !pluck_node.receiver&.const_type?

    add_offense(uniq_node.loc.selector) do |corrector|
      autocorrect(corrector, uniq_node, pluck_node)
    end
  end
end