class RuboCop::Cop::Performance::Count

Model.select(:value).count
Model.select(‘field AS field_one’).count
[1, 2, 3].count { |e| e < 2 && e.even? }
[1, 2, 3].count { |e| e > 2 && e.odd? }
[1, 2, 3].count { |e| e < 2 }
[1, 2, 3].count { |e| e > 2 }
# good
array.select(&:value).count
[1, 2, 3].reject { |e| e > 2 }.count { |e| e.even? }
[1, 2, 3].select { |e| e > 2 }.count { |e| e.odd? }
[1, 2, 3].reject { |e| e > 2 }.length
[1, 2, 3].select { |e| e > 2 }.length
[1, 2, 3].reject { |e| e > 2 }.size
[1, 2, 3].select { |e| e > 2 }.size
# bad
@example
—-
‘Model.where(id: [1, 2, 3]).to_a.count { |m| m.method == true }`
becomes:
—-
`Model.where(id: [1, 2, 3]).select { |m| m.method == true }.size`
—-
[source,ruby]

For example:
make `count` work with a block is to call `to_a.count {…}`.
array and then run the block on the array. A simple work around to
Other methods, such as `select`, will convert the association to an
frameworks. Before Rails 5.1, `ActiveRecord` will ignore the block that is passed to `count`.
This cop is unsafe because it has known compatibility issues with `ActiveRecord` and other
@safety
passed to the `count` call.
follow calls to `select`, `find_all`, `filter` or `reject`. Querying logic can instead be
Identifies usages of `count` on an `Enumerable` that

def autocorrect(corrector, node, selector_node, selector)

def autocorrect(corrector, node, selector_node, selector)
  selector_loc = selector_node.loc.selector
  range = source_starting_at(node) { |n| n.loc.dot.begin_pos }
  corrector.remove(range)
  corrector.replace(selector_loc, 'count')
  negate_reject(corrector, node) if selector == :reject
end

def eligible_node?(node)

def eligible_node?(node)
  !(node.parent && node.parent.block_type?)
end

def negate_block_pass_as_inline_block(node)

def negate_block_pass_as_inline_block(node)
  if node.last_argument.children.first.sym_type?
    " { |element| !element.#{node.last_argument.children.first.value} }"
  else
    " { !#{node.last_argument.children.first.source}.call }"
  end
end

def negate_block_pass_reject(corrector, node)

def negate_block_pass_reject(corrector, node)
  corrector.replace(
    node.receiver.source_range.with(begin_pos: node.receiver.loc.begin.begin_pos),
    negate_block_pass_as_inline_block(node.receiver)
  )
end

def negate_block_reject(corrector, node)

def negate_block_reject(corrector, node)
  target =
    if node.receiver.body.begin_type?
      node.receiver.body.children.last
    else
      node.receiver.body
    end
  corrector.replace(target, negate_expression(target))
end

def negate_expression(node)

def negate_expression(node)
  "!(#{node.source})"
end

def negate_reject(corrector, node)

def negate_reject(corrector, node)
  if node.receiver.call_type?
    negate_block_pass_reject(corrector, node)
  else
    negate_block_reject(corrector, node)
  end
end

def on_send(node)

def on_send(node)
  count_candidate?(node) do |selector_node, selector, counter|
    return unless eligible_node?(node)
    range = source_starting_at(node) do
      selector_node.loc.selector.begin_pos
    end
    add_offense(range, message: format(MSG, selector: selector, counter: counter)) do |corrector|
      autocorrect(corrector, node, selector_node, selector)
    end
  end
end

def source_starting_at(node)

def source_starting_at(node)
  begin_pos = if block_given?
                yield node
              else
                node.source_range.begin_pos
              end
  range_between(begin_pos, node.source_range.end_pos)
end