Class: RuboCop::Cop::Rails::PluckInWhere

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

Overview

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 by running as a subquery.

This cop has two modes of enforcement. When the ‘EnforcedStyle` is set to `conservative` (the default), only calls to `pluck` on a constant (e.g. a model class) within `where` are considered offenses.

Examples:

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

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

EnforcedStyle: conservative (default)

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

EnforcedStyle: aggressive

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

Constant Summary collapse

MSG_SELECT =
'Use `select` instead of `pluck` within `where` query method.'
MSG_IDS =
'Use `select(:id)` instead of `ids` within `where` query method.'
RESTRICT_ON_SEND =
%i[pluck ids].freeze

Constants included from ActiveRecordHelper

ActiveRecordHelper::WHERE_METHODS

Instance Method Summary collapse

Methods included from ActiveRecordHelper

#external_dependency_checksum, #foreign_key_of, #in_where?, #inherit_active_record_base?, #polymorphic?, #resolve_relation_into_column, #schema, #table_name

Instance Method Details

#on_send(node) ⇒ Object Also known as: on_csend



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/rubocop/cop/rails/pluck_in_where.rb', line 59

def on_send(node)
  return unless in_where?(node)
  return if style == :conservative && !root_receiver(node)&.const_type?

  range = node.loc.selector

  if node.method?(:ids)
    replacement = 'select(:id)'
    message = MSG_IDS
  else
    replacement = 'select'
    message = MSG_SELECT
  end

  add_offense(range, message: message) do |corrector|
    corrector.replace(range, replacement)
  end
end