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