class RuboCop::Cop::Style::MapCompactWithConditionalBlock

Prefer ‘select` or `reject` over `map { … }.compact`.

@example

# bad
array.map { |e| some_condition? ? e : next }.compact

# bad
array.map do |e|
  if some_condition?
    e
  else
    next
  end
end.compact

# bad
array.map do |e|
  next if some_condition?

  e
end.compact

# bad
array.map do |e|
  e if some_condition?
end.compact

# good
array.select { |e| some_condition? }

# good
array.reject { |e| some_condition? }

Constants

MSG

Public Instance Methods

on_send(node) click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 72
def on_send(node)
  map_and_compact?(node) do |block_argument_node, condition_node, return_value_node|
    return unless returns_block_argument?(block_argument_node, return_value_node)
    return if condition_node.parent.elsif?

    method = truthy_branch?(return_value_node) ? 'select' : 'reject'
    range = range(node)

    add_offense(range, message: format(MSG, method: method)) do |corrector|
      corrector.replace(
        range,
        "#{method} { |#{block_argument_node.source}| #{condition_node.source} }"
      )
    end
  end
end

Private Instance Methods

range(node) click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 125
def range(node)
  buffer = node.loc.expression.source_buffer
  map_node = node.receiver.send_node
  begin_pos = map_node.loc.selector.begin_pos
  end_pos = node.loc.expression.end_pos

  Parser::Source::Range.new(buffer, begin_pos, end_pos)
end
returns_block_argument?(block_argument_node, return_value_node) click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 91
def returns_block_argument?(block_argument_node, return_value_node)
  block_argument_node.name == return_value_node.children.first
end
truthy_branch?(node) click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 95
def truthy_branch?(node)
  if node.parent.begin_type?
    truthy_branch_for_guard?(node)
  elsif node.parent.next_type?
    truthy_branch_for_if?(node.parent)
  else
    truthy_branch_for_if?(node)
  end
end
truthy_branch_for_guard?(node) click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 115
def truthy_branch_for_guard?(node)
  if_node = node.left_sibling

  if if_node.if? || if_node.ternary?
    if_node.else_branch.nil?
  elsif if_node.unless?
    if_node.if_branch.nil?
  end
end
truthy_branch_for_if?(node) click to toggle source
# File lib/rubocop/cop/style/map_compact_with_conditional_block.rb, line 105
def truthy_branch_for_if?(node)
  if_node = node.parent

  if if_node.if? || if_node.ternary?
    if_node.if_branch == node
  elsif if_node.unless?
    if_node.else_branch == node
  end
end