class RuboCop::Cop::Style::RedundantFilterChain

Identifies usages of ‘any?`, `empty?` or `none?` predicate methods chained to `select`/`filter`/`find_all` and change them to use predicate method instead.

@safety

This cop's autocorrection is unsafe because `array.select.any?` evaluates all elements
through the `select` method, while `array.any?` uses short-circuit evaluation.
In other words, `array.select.any?` guarantees the evaluation of every element,
but `array.any?` does not necessarily evaluate all of them.

@example

# bad
arr.select { |x| x > 1 }.any?

# good
arr.any? { |x| x > 1 }

# bad
arr.select { |x| x > 1 }.empty?
arr.select { |x| x > 1 }.none?

# good
arr.none? { |x| x > 1 }

# good
relation.select(:name).any?
arr.select { |x| x > 1 }.any?(&:odd?)

@example AllCops:ActiveSupportExtensionsEnabled: false (default)

# good
arr.select { |x| x > 1 }.many?

# good
arr.select { |x| x > 1 }.present?

@example AllCops:ActiveSupportExtensionsEnabled: true

# bad
arr.select { |x| x > 1 }.many?

# good
arr.many? { |x| x > 1 }

# bad
arr.select { |x| x > 1 }.present?

# good
arr.any? { |x| x > 1 }

Constants

MSG
RAILS_METHODS
REPLACEMENT_METHODS
RESTRICT_ON_SEND

Public Instance Methods

on_csend(node)
Alias for: on_send
on_send(node) click to toggle source
# File lib/rubocop/cop/style/redundant_filter_chain.rb, line 81
def on_send(node)
  return if node.arguments? || node.block_literal?

  select_predicate?(node) do |select_node, filter_method|
    return if RAILS_METHODS.include?(filter_method) && !active_support_extensions_enabled?

    register_offense(select_node, node)
  end
end
Also aliased as: on_csend

Private Instance Methods

offense_range(select_node, predicate_node) click to toggle source
# File lib/rubocop/cop/style/redundant_filter_chain.rb, line 108
def offense_range(select_node, predicate_node)
  select_node.loc.selector.join(predicate_node.loc.selector)
end
predicate_range(predicate_node) click to toggle source
# File lib/rubocop/cop/style/redundant_filter_chain.rb, line 112
def predicate_range(predicate_node)
  predicate_node.receiver.source_range.end.join(predicate_node.loc.selector)
end
register_offense(select_node, predicate_node) click to toggle source
# File lib/rubocop/cop/style/redundant_filter_chain.rb, line 94
def register_offense(select_node, predicate_node)
  replacement = REPLACEMENT_METHODS[predicate_node.method_name]
  message = format(MSG, prefer: replacement,
                        first_method: select_node.method_name,
                        second_method: predicate_node.method_name)

  offense_range = offense_range(select_node, predicate_node)

  add_offense(offense_range, message: message) do |corrector|
    corrector.remove(predicate_range(predicate_node))
    corrector.replace(select_node.loc.selector, replacement)
  end
end