class RuboCop::Cop::Performance::SelectMap
ary.filter_map { |o| o.bar if o.foo }
# good
ary.filter(&:foo).map(&:bar)
ary.select(&:foo).map(&:bar)
# bad
@example
This cop identifies places where ‘select.map` can be replaced by `filter_map`.
In Ruby 2.7, `Enumerable#filter_map` has been added.
def map_method_candidate(node)
def map_method_candidate(node) return unless (parent = node.parent) if parent.block_type? && parent.parent&.call_type? parent.parent elsif parent.call_type? parent end end
def offense_range(node, map_method)
def offense_range(node, map_method) range_between(node.loc.selector.begin_pos, map_method.source_range.end_pos) end
def on_send(node)
def on_send(node) return if (first_argument = node.first_argument) && !first_argument.block_pass_type? return unless (send_node = map_method_candidate(node)) return unless send_node.method?(:map) map_method = send_node.parent&.block_type? ? send_node.parent : send_node range = offense_range(node, map_method) add_offense(range, message: format(MSG, method_name: node.method_name)) end