Class: RuboCop::Cop::Rails::Pick

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector, TargetRailsVersion
Defined in:
lib/rubocop/cop/rails/pick.rb

Overview

Enforces the use of pick over pluck(...).first.

Using pluck followed by first creates an intermediate array, which pick avoids. When called on an Active Record relation, pick adds a limit to the query so that only one value is fetched from the database.

Examples:

# bad
Model.pluck(:a).first
[{ a: :b, c: :d }].pluck(:a, :b).first

# good
Model.pick(:a)
[{ a: :b, c: :d }].pick(:a, :b)

Cop Safety Information:

  • This cop is unsafe because pluck is defined on both ActiveRecord::Relation and Enumerable, whereas pick is only defined on ActiveRecord::Relation in Rails 6.0. This was addressed in Rails 6.1 via rails/rails#38760, at which point the cop is safe.

    See: https://github.com/rubocop/rubocop-rails/pull/249

Constant Summary collapse

MSG =
'Prefer `pick(%<args>s)` over `%<current>s`.'
RESTRICT_ON_SEND =
%i[first].freeze

Constants included from TargetRailsVersion

TargetRailsVersion::USES_REQUIRES_GEM_API

Instance Method Summary collapse

Methods included from TargetRailsVersion

minimum_target_rails_version, support_target_rails_version?

Instance Method Details

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



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/rubocop/cop/rails/pick.rb', line 40

def on_send(node)
  pick_candidate?(node) do
    receiver = node.receiver
    receiver_selector = receiver.loc.selector
    node_selector = node.loc.selector
    range = receiver_selector.join(node_selector)

    add_offense(range, message: message(receiver, range)) do |corrector|
      first_range = receiver.source_range.end.join(node_selector)

      corrector.remove(first_range)
      corrector.replace(receiver_selector, 'pick')
    end
  end
end