class RuboCop::Cop::Rails::PluckInWhere

This cop identifies places where `pluck` is used in `where` query methods and can be replaced with `select`.

Since `pluck` is an eager method and hits the database immediately, using `select` helps to avoid additional database queries.

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) in the `where` is used as offenses.

When the EnforcedStyle is aggressive then all calls to `pluck` in the `where` is used as offenses. This may lead to false positives as the cop cannot replace to `select` between calls to `pluck` on an `ActiveRecord::Relation` instance vs a call to `pluck` on an `Array` instance.

@example

# bad
Post.where(user_id: User.active.pluck(:id))

# good
Post.where(user_id: User.active.select(:id))
Post.where(user_id: active_users.select(:id))

@example EnforcedStyle: conservative (default)

# good
Post.where(user_id: active_users.pluck(:id))

@example EnforcedStyle: aggressive

# bad
Post.where(user_id: active_users.pluck(:id))

Constants

MSG
RESTRICT_ON_SEND

Public Instance Methods

on_send(node) click to toggle source
# File lib/rubocop/cop/rails/pluck_in_where.rb, line 45
def on_send(node)
  return unless in_where?(node)
  return if style == :conservative && !root_receiver(node)&.const_type?

  range = node.loc.selector

  add_offense(range) do |corrector|
    corrector.replace(range, 'select')
  end
end

Private Instance Methods

root_receiver(node) click to toggle source
# File lib/rubocop/cop/rails/pluck_in_where.rb, line 58
def root_receiver(node)
  receiver = node.receiver

  if receiver&.send_type?
    root_receiver(receiver)
  else
    receiver
  end
end