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